home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / ppp / dp-2.3 / sys / RCS / dp_if.c,v next >
Encoding:
Text File  |  1992-12-13  |  102.5 KB  |  4,912 lines

  1. head     1.35;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.35
  10. date     92.12.14.07.29.09;  author ks;  state Exp;
  11. branches ;
  12. next     1.34;
  13.  
  14. 1.34
  15. date     92.12.11.08.10.18;  author ks;  state Exp;
  16. branches ;
  17. next     1.33;
  18.  
  19. 1.33
  20. date     92.12.11.07.57.57;  author ks;  state Exp;
  21. branches ;
  22. next     1.32;
  23.  
  24. 1.32
  25. date     92.11.25.14.11.05;  author ks;  state Exp;
  26. branches ;
  27. next     1.31;
  28.  
  29. 1.31
  30. date     92.10.08.12.37.02;  author ks;  state Exp;
  31. branches ;
  32. next     1.30;
  33.  
  34. 1.30
  35. date     92.09.03.12.13.22;  author ks;  state Exp;
  36. branches ;
  37. next     1.29;
  38.  
  39. 1.29
  40. date     92.07.24.10.01.35;  author ks;  state Exp;
  41. branches ;
  42. next     1.28;
  43.  
  44. 1.28
  45. date     92.07.16.08.24.40;  author ks;  state Exp;
  46. branches ;
  47. next     1.27;
  48.  
  49. 1.27
  50. date     92.06.22.13.43.21;  author ks;  state Exp;
  51. branches ;
  52. next     1.26;
  53.  
  54. 1.26
  55. date     92.06.22.13.38.53;  author ks;  state Exp;
  56. branches ;
  57. next     1.25;
  58.  
  59. 1.25
  60. date     92.06.12.09.37.56;  author ks;  state Exp;
  61. branches ;
  62. next     1.24;
  63.  
  64. 1.24
  65. date     92.05.22.13.49.17;  author ks;  state Exp;
  66. branches ;
  67. next     1.23;
  68.  
  69. 1.23
  70. date     92.05.21.09.53.48;  author ks;  state Exp;
  71. branches ;
  72. next     1.22;
  73.  
  74. 1.22
  75. date     92.05.20.10.15.38;  author ks;  state Exp;
  76. branches ;
  77. next     1.21;
  78.  
  79. 1.21
  80. date     92.04.23.13.44.25;  author ks;  state Exp;
  81. branches ;
  82. next     1.20;
  83.  
  84. 1.20
  85. date     92.03.17.12.45.06;  author ks;  state Exp;
  86. branches ;
  87. next     1.19;
  88.  
  89. 1.19
  90. date     92.03.12.15.34.54;  author ks;  state Exp;
  91. branches ;
  92. next     1.18;
  93.  
  94. 1.18
  95. date     92.03.12.13.26.15;  author ks;  state Exp;
  96. branches ;
  97. next     1.17;
  98.  
  99. 1.17
  100. date     92.03.10.07.33.56;  author ks;  state Exp;
  101. branches ;
  102. next     1.16;
  103.  
  104. 1.16
  105. date     92.03.05.12.31.20;  author ks;  state Exp;
  106. branches ;
  107. next     1.15;
  108.  
  109. 1.15
  110. date     92.03.05.10.25.14;  author ks;  state Exp;
  111. branches ;
  112. next     1.14;
  113.  
  114. 1.14
  115. date     92.03.04.14.32.49;  author ks;  state Exp;
  116. branches ;
  117. next     1.13;
  118.  
  119. 1.13
  120. date     92.03.04.14.14.00;  author ks;  state Exp;
  121. branches ;
  122. next     1.12;
  123.  
  124. 1.12
  125. date     92.02.26.11.02.46;  author ks;  state Exp;
  126. branches ;
  127. next     1.11;
  128.  
  129. 1.11
  130. date     91.12.18.08.39.58;  author ks;  state Exp;
  131. branches ;
  132. next     1.10;
  133.  
  134. 1.10
  135. date     91.12.03.09.31.47;  author ks;  state Exp;
  136. branches ;
  137. next     1.9;
  138.  
  139. 1.9
  140. date     91.10.10.14.22.26;  author ks;  state Exp;
  141. branches ;
  142. next     1.8;
  143.  
  144. 1.8
  145. date     91.10.04.07.33.21;  author ks;  state Exp;
  146. branches ;
  147. next     1.7;
  148.  
  149. 1.7
  150. date     91.10.03.12.42.33;  author ks;  state Exp;
  151. branches ;
  152. next     1.6;
  153.  
  154. 1.6
  155. date     91.10.01.16.47.13;  author ks;  state Exp;
  156. branches ;
  157. next     1.5;
  158.  
  159. 1.5
  160. date     91.10.01.08.16.40;  author ks;  state Exp;
  161. branches ;
  162. next     1.4;
  163.  
  164. 1.4
  165. date     91.09.30.15.43.54;  author ks;  state Exp;
  166. branches ;
  167. next     1.3;
  168.  
  169. 1.3
  170. date     91.09.27.14.10.16;  author ks;  state Exp;
  171. branches ;
  172. next     1.2;
  173.  
  174. 1.2
  175. date     91.09.12.15.58.19;  author ks;  state Exp;
  176. branches ;
  177. next     1.1;
  178.  
  179. 1.1
  180. date     91.09.11.10.28.02;  author ks;  state Exp;
  181. branches ;
  182. next     ;
  183.  
  184.  
  185. desc
  186. @From ppp_if.c
  187. @
  188.  
  189.  
  190. 1.35
  191. log
  192. @printf argument fixed..
  193. @
  194. text
  195. @/*
  196.  * dp_if.c - Streams PPP top level module handles if_ and packetizing
  197.  * PPP packets.
  198.  * Copyright (C) 1990  Brad K. Clements, All Rights Reserved
  199.  */
  200. /*
  201.  * Copyright (c) 1992 Purdue University
  202.  * All rights reserved.
  203.  *
  204.  * Redistribution and use in source and binary forms are permitted
  205.  * provided that the above copyright notice and this paragraph are
  206.  * duplicated in all such forms and that any documentation,
  207.  * advertising materials, and other materials related to such
  208.  * distribution and use acknowledge that the software was developed
  209.  * by Purdue University.  The name of the University may not be used
  210.  * to endorse or promote products derived * from this software without
  211.  * specific prior written permission.
  212.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  213.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  214.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  215.  *
  216.  * Note: this copyright applies to portions of this software developed
  217.  * at Purdue beyond the software covered by the original copyright.
  218.  */
  219.  
  220. /*
  221.  * This file contains 3 basic parts, which are somewhat mixed together.
  222.  *
  223.  * "dpif" streams module
  224.  *    This can be pushed on a stream to connect it to a "dp" network
  225.  *    interface. It routes PPP packets through the stream to the user
  226.  *    process and network packets (IP) through the "dp" network interface.
  227.  * "dp" network interface
  228.  *    This is a network interface (like an ethernet driver), that implements
  229.  *    a Point to Point TCP/IP network interface.  It communicates with
  230.  *    the "dpif" streams module for input and output on the serial
  231.  *    stream and passes packets back and forth to the kernel networking
  232.  *    modules.
  233.  * "pppdial" streams device
  234.  *     This is a streams device that can be opened by a user process.
  235.  *    Messages are sent to the user process through this device when
  236.  *    the "dp" network interface needs to establish a connection to
  237.  *    send packets on a particular network interface.
  238.  */
  239. #define    VJC    1
  240. #include <sys/types.h>
  241.  
  242. #ifndef LOADABLE
  243. #include "dp.h"
  244. #endif
  245. #if NDP > 0
  246.  
  247. #define    STREAMS    1
  248.  
  249. #define    PPP_STATS    1
  250. #define PPP_SNIT    1 /* pass packets to Streams Network Interface Tap */
  251.  
  252. #define    DEBUGS    1
  253.  
  254. #include <sys/param.h>
  255. #include <sys/stream.h>
  256. #include <sys/stropts.h>
  257.  
  258. #include <sys/user.h>
  259. #include <sys/systm.h>
  260. #include <sys/mbuf.h>
  261. #include <sys/socket.h>
  262. #include <sys/errno.h>
  263. #include <sys/ioctl.h>
  264. #include <sys/file.h>
  265. #include <sys/uio.h>
  266. #include <sys/signal.h>
  267. #include <net/if.h>
  268. #include <net/netisr.h>
  269. #include <netinet/in.h>
  270. #include <netinet/in_systm.h>
  271. #include <netinet/in_var.h>
  272. #include <netinet/ip.h>
  273. #ifdef    PPP_STATS
  274. #ifdef    LOADABLE
  275. #include "slip_var.h"
  276. #else
  277. #include <sys/slip_var.h>
  278. #endif
  279. #define    INCR(comp)    ++p->pii_stats.comp
  280. #else
  281. #define    INCR(comp)
  282. #endif
  283.  
  284. #ifdef    VJC
  285. #ifdef    LOADABLE
  286. #include "slcompress.h"
  287. #else
  288. #include <sys/slcompress.h>
  289. #endif
  290. #endif
  291. #ifdef    LOADABLE
  292. #include "if_ppp.h"
  293. #include "dp_str.h"
  294. #else
  295. #include <sys/if_ppp.h>
  296. #include <sys/dp_str.h>
  297. #endif
  298. #include <netinet/tcp.h>
  299. #ifdef    DEBUGS
  300. #include <sys/syslog.h>
  301. static char *dus_str[] = {
  302.     "ACTIVE",
  303.     "ACTIVEC",
  304.     "ACTIVEU",
  305.     "WAITING",
  306.     "FAILCALL",
  307.     "DISCON",
  308.     "DOWN",
  309. };
  310. static char *cstat_str[] = {
  311.     "FAILURE",
  312.     "SUCCESS",
  313.     "IN_PROGRESS",
  314.     "NO_MODEM"
  315. };
  316. #define    DLOG(s,a)    if (dp_if_debug) log(LOG_INFO, s, a)
  317. #define    DLOG2(s,a1,a2)    if (dp_if_debug) log(LOG_INFO, s, a1, a2)
  318. #define    DLOG3(s,a,b,c)    if (dp_if_debug) log(LOG_INFO, s, a, b, c)
  319. #define    DLOG5(s,a,b,c,d,e) if (dp_if_debug) log(LOG_INFO, s, a, b, c, d, e)
  320. #define DLOGFLAGS(s)    DLOG2(s, p->pii_ifnet.if_flags, p->pii_flags)
  321. #define    DLOGSTATE(s)    if (dp_if_debug) log(LOG_INFO, s, dus_str[p->pii_dustate])
  322. int    dp_if_debug=0;
  323. int    dp_ftimo_debug=0;
  324. #define    static    
  325. #define    DLOG_ACTIVE(event)    if (dp_if_debug || dp_active_debug) log(LOG_INFO, "%c %s %d %d/%d", xmit ? 'T' : 'R', (event), act->da_nactive, act->da_misses, act->da_lookups)
  326. int dp_active_debug = 0;
  327. #else
  328. #define    DLOG(s,a)    {}
  329. #define    DLOG2(s,a1,a2)    {}
  330. #define    DLOG3(s,a,b,c)    {}
  331. #define    DLOG5(s,a,b,c,d,e) {}
  332. #define DLOGFLAGS(s)    {}
  333. #define    DLOGSTATE(s)    {}
  334. #define    DLOG_ACTIVE(s)    {}
  335. #endif
  336.  
  337. #ifdef PPP_SNIT
  338. #include <net/nit_if.h>
  339. #include <netinet/if_ether.h>
  340. /* Use a fake link level header to make etherfind and tcpdump happy. */
  341. static struct ether_header header = {{1}, {2}, ETHERTYPE_IP};
  342. static struct nit_if nif = {(caddr_t)&header, sizeof(header), 0, 0};
  343. #endif
  344.  
  345. #ifdef LOADABLE
  346. #include <sys/conf.h>
  347. #include <sys/buf.h>
  348. #include <sundev/mbvar.h>
  349. #include <sun/autoconf.h>
  350. #include <sun/vddrv.h>
  351. #endif
  352.  
  353. static    int    dp_if_open(), dp_if_close(),
  354.         dp_if_rput(), dp_if_wput(),
  355.         dp_if_wsrv(), dp_if_rsrv();
  356.  
  357. static     struct    module_info    dp_minfo ={
  358.     0xbad,"dpif",0, INFPSZ, 16384, 4096
  359. };
  360.  
  361. static    struct    qinit    dpr_init = {
  362.     dp_if_rput, dp_if_rsrv, dp_if_open, dp_if_close, NULL, &dp_minfo, NULL
  363. };
  364. static    struct    qinit    dpw_init = {
  365.     dp_if_wput, dp_if_wsrv, dp_if_open, dp_if_close, NULL, &dp_minfo, NULL
  366. };
  367. struct    streamtab    dp_ifinfo = {
  368.     &dpr_init, &dpw_init, NULL, NULL, NULL
  369. };
  370.  
  371. typedef    struct dp_if_info    PII;
  372.  
  373. PII    dupii[NDP];
  374.  
  375. static int dp_start(), dp_timer(), dp_ioctl(), dp_output();
  376. static void dp_flush();
  377.  
  378. static int dp_deftimo[PII_DP_NSTATES] = {
  379.     DP_DEF_ATIMEO,        /* Activity Timeout */
  380.     DP_DEF_CTIMEO,        /* Last TCP Close Timeout */
  381.     DP_DEF_UTIMEO,        /* Non-TCP traffic timeout */
  382.     DP_DEF_WTIMEO,        /* Call Wait Timeout */
  383.     DP_DEF_FTIMEO,        /* Failed Call Timeout */
  384.     DP_NO_TIMEOUT,        /* No Disconnect Timeout */
  385.     DP_NO_TIMEOUT        /* No Down Timeout */
  386. };
  387.  
  388. static void dp_active_init(),
  389.         dp_active_tinit(),
  390.         dp_active();
  391.  
  392. static int
  393. dp_attach(unit)
  394. int unit;
  395. {
  396.     register PII *p = &dupii[unit];
  397.     register struct ifnet *ifp = &dupii[unit].pii_ifnet;
  398.  
  399.     ifp->if_name = "dp";
  400.     ifp->if_mtu = PPP_MTU;
  401.     ifp->if_flags = IFF_POINTOPOINT;
  402.     ifp->if_unit = unit;
  403.     ifp->if_ioctl = dp_ioctl;
  404.     ifp->if_output = dp_output;
  405.     ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  406.     ifp->if_watchdog = dp_timer;
  407.     ifp->if_timer = 0;
  408.     if_attach(ifp);
  409.     p->pii_flags |= PII_FLAGS_ATTACHED;
  410. }
  411.  
  412. static void
  413. dp_init(unit)
  414. int unit;
  415. {
  416.     register PII *p = &dupii[unit];
  417.     register struct ifnet *ifp = &p->pii_ifnet;
  418.     register int i;
  419.  
  420.     /*
  421.      * Initialize the dialup stuff..
  422.      */
  423.  
  424.     if (!(ifp->if_flags & IFF_UP))
  425.     return;
  426.     if (!(p->pii_flags & PII_FLAGS_INITTED)) {
  427.     p->pii_flags |= PII_FLAGS_INITTED;
  428.     for (i = 0 ; i < PII_DP_NSTATES ; i++)
  429.         p->pii_timo[i] = dp_deftimo[i];
  430.     dp_state(p, PII_DPS_DISCON);
  431.     DLOG3("dp_init: timeouts %d %d %d\n", p->pii_timo[0] * DP_HZ,
  432.           p->pii_timo[1] * DP_HZ, p->pii_timo[2] * DP_HZ);
  433.     }
  434.  
  435.     ifp->if_flags |= IFF_UP|IFF_RUNNING;
  436. }
  437.  
  438. static int
  439. dp_if_open(q, dev, flag, sflag)
  440. queue_t    *q;
  441. dev_t    dev;
  442. int    flag,
  443.     sflag;
  444. {
  445.     if (!suser()) {
  446.     u.u_error = EPERM;
  447.     return OPENFAIL;
  448.     }
  449.     return 0;
  450. }
  451.  
  452. static int
  453. dp_if_unit(q, unit)
  454. queue_t    *q;
  455. int unit;
  456. {
  457.     register PII *p;
  458.     int    s;
  459.  
  460.     DLOG("dp_if_unit: enter %d\n", unit);
  461.     if (unit < 0 || unit >= NDP)
  462.     return EINVAL;
  463.     if (q->q_ptr)
  464.     return EBUSY;
  465.  
  466.     s = splstr();
  467.     p = &dupii[unit];
  468.  
  469.     if (p->pii_writeq) {
  470.     splx(s);
  471.     return EBUSY;
  472.     }
  473. #ifdef    VJC
  474. #ifdef    PPP_STATS
  475.     bzero(&p->pii_stats,sizeof(p->pii_stats));
  476. #endif
  477.     sl_compress_init(&p->pii_sc_comp);
  478. #endif
  479.     dp_active_init(&p->pii_active);
  480.     if (!(p->pii_flags & PII_FLAGS_ATTACHED))
  481.     dp_attach(unit); /* attach it */
  482.     p->pii_writeq = q;
  483.     RD(q)->q_ptr = q->q_ptr = (caddr_t) p;    /* set write Q and read Q to point here */
  484.     p->pii_flags |= PII_FLAGS_INUSE|PII_FLAGS_ATTACHED;
  485.     DLOG("dp_if_unit: exit %d\n", unit);
  486.     splx(s);
  487.     return 0;
  488. }
  489.  
  490. static int
  491. dp_if_close(q)
  492.     queue_t    *q;            /* queue info */
  493. {
  494.     PII    *p = (PII *) q->q_ptr;
  495.     int    s;
  496.  
  497.     s = splimp();
  498.     dp_flush(p, q);
  499.     if (p) {
  500.     p->pii_flags &= ~PII_FLAGS_INUSE;
  501.     switch (p->pii_dustate) {
  502.      case PII_DPS_DOWN:
  503.         break;
  504.      case PII_DPS_DISCON:
  505.      case PII_DPS_WAITING:
  506.      case PII_DPS_ACTIVE:
  507.      case PII_DPS_FAILCALL:
  508.         dp_state(p, PII_DPS_DISCON);
  509.         break;
  510.      default:
  511.         DLOG("dp_if_close: unknown state %d\n", p->pii_dustate);
  512.         break;
  513.     }
  514.     p->pii_writeq = (queue_t *)0;
  515.     q->q_ptr = (char *)0;
  516.     DLOG("dp_if%d: closed\n", (p-dupii)/sizeof(PII));
  517.     }
  518.     else
  519.     DLOG("dp_if: closed\n", p);
  520.     splx(s);
  521.     return(0);            /* no work to be done */
  522. }
  523.  
  524. static void
  525. dp_flush(p, q)
  526. register PII *p;
  527. register queue_t *q;
  528. {
  529.     if (p)
  530.     if_qflush(&p->pii_ifnet.if_snd);
  531.     if (q) {
  532.     flushq(q, FLUSHALL);
  533.     flushq(OTHERQ(q), FLUSHALL);
  534.     }
  535. }
  536.  
  537.  
  538. static int
  539. dp_ioc_sint(mp, i, valp)
  540. register mblk_t *mp;
  541. register struct iocblk *i;
  542. int *valp;
  543. {
  544.     if (i->ioc_count != sizeof(int)) {
  545.     i->ioc_error = EINVAL;
  546.     return -1;
  547.     }
  548.     *valp = *(int *)mp->b_cont->b_rptr;
  549.     return 0;
  550. }
  551.  
  552. /*
  553.  *
  554.  * dp_callstat() provides for the following state transitions..
  555.  *
  556.  * State    Status         New State
  557.  * FAILCALL    IN_PROGRESS    WAITING        (dplogin starting..)
  558.  * DISCON    IN_PROGRESS    WAITING        (dplogin starting..)
  559.  * WAITING    FAILURE        FAILCALL    (couldn't complete call)
  560.  * WAITING    NO_MODEM    DISCON        (no modems, immediate retry ok)
  561.  * WAITING    SUCCESS        ACTIVE        (start packets flowing)
  562.  */
  563.     
  564. static int
  565. dp_callstat(p, stat)
  566. register PII *p;
  567. char stat;
  568. {
  569. #ifdef    DEBUGS
  570.     if (dp_if_debug) {
  571.     if (DP_VALID_STATUS(stat))
  572.         log(LOG_INFO, "dp_callstat: state %s stat %s\n",
  573.         dus_str[p->pii_dustate], cstat_str[stat]);
  574.     else
  575.         log(LOG_INFO, "dp_callstat: state %s stat %d\n",
  576.         dus_str[p->pii_dustate], stat);
  577.     }
  578. #endif
  579.     switch (p->pii_dustate) {
  580.      case PII_DPS_DOWN:
  581.      case PII_DPS_ACTIVE:
  582.     break;
  583.  
  584.      /*
  585.       * Not connected, so transition to WAITING if dplogin is starting up..
  586.       */
  587.      case PII_DPS_FAILCALL:
  588.      case PII_DPS_DISCON:
  589.     switch (stat) {
  590.      case DP_IN_PROGRESS:
  591.         dp_state(p, PII_DPS_WAITING);
  592.         break;
  593.      case DP_SUCCESS:
  594.         dp_state(p, PII_DPS_ACTIVE);
  595.         break;
  596.     }
  597.  
  598.      /*
  599.       * Waiting for a connection to be established.
  600.       * Respond properly to the result returned.
  601.       */
  602.      case PII_DPS_WAITING:
  603.     switch (stat) {
  604.      case DP_SUCCESS:
  605.         dp_state(p, PII_DPS_ACTIVE);
  606.         (void)dp_start(p);
  607.         break;
  608.      case DP_FAILURE:
  609.         dp_state(p, PII_DPS_FAILCALL);
  610.         dp_flush(p, p->pii_writeq);
  611.         break;
  612.      case DP_NO_MODEM:
  613.         dp_state(p, PII_DPS_DISCON);
  614.         dp_flush(p, p->pii_writeq);
  615.     }
  616.     break;
  617.     }
  618. }
  619.  
  620. static int
  621. dp_if_wput(q, mp)
  622. queue_t  *q;
  623. register mblk_t *mp;
  624. {
  625.  
  626.     register struct iocblk *i;
  627.     register PII *p;
  628.     int x;
  629.  
  630.     switch (mp->b_datap->db_type) {
  631.      case  M_FLUSH:
  632.     if (*mp->b_rptr & FLUSHW)
  633.         flushq(q, FLUSHDATA);
  634.     putnext(q, mp);        /* send it along too */
  635.     break;
  636.  
  637.      case M_DATA:
  638.     if (!q->q_ptr) {
  639.         mp->b_datap->db_type = M_ERROR;
  640.         mp->b_rptr = mp->b_wptr = mp->b_datap->db_base;
  641.         *mp->b_wptr++ = ENXIO;
  642.         qreply(q, mp);
  643.     }
  644.     else
  645.         putq(q, mp);    /* queue it for my service routine */
  646.     break;
  647.  
  648.      case M_IOCTL:
  649.     i = (struct iocblk *) mp->b_rptr;
  650.     p = (PII *) q->q_ptr;
  651.     if (!p && i->ioc_cmd != SIOCSIFUNIT)
  652.         goto passalong;
  653.  
  654.     switch (i->ioc_cmd) {
  655.      case SIOCSIFCOMPAC:    /* enable or disable AC compression */
  656.         if (i->ioc_count != sizeof(u_char)) 
  657.         goto passalong;
  658.         DLOG("dp_if: SIFCOMPAC %d\n",  *(u_char *) mp->b_cont->b_rptr);
  659.         if ( *(u_char *) mp->b_cont->b_rptr) 
  660.         p->pii_flags |= PII_FLAGS_COMPAC;
  661.         else
  662.         p->pii_flags &= ~PII_FLAGS_COMPAC;
  663.         goto passalong;
  664.     
  665.      case SIOCSIFCOMPPROT:    /* enable or disable PROT  compression */
  666.         DLOG("dp_if: SIFCOMPPROT %d\n",  *(u_char *) mp->b_cont->b_rptr);
  667.         if (i->ioc_count != sizeof(u_char))
  668.         goto passalong;
  669.         if ( *(u_char *) mp->b_cont->b_rptr) 
  670.         p->pii_flags |= PII_FLAGS_COMPPROT;
  671.         else
  672.         p->pii_flags &= ~PII_FLAGS_COMPPROT;
  673.         goto passalong;
  674.  
  675.      case SIOCSIFVJCOMP:    /* enable or disable VJ compression */
  676. #ifdef    VJC
  677.         if (i->ioc_count != sizeof(u_char)) 
  678.         goto passalong;
  679.         DLOG("dp_if: SIFVJCOMP %d\n",  *(u_char *) mp->b_cont->b_rptr);
  680.         if ( *(u_char *) mp->b_cont->b_rptr) 
  681.         p->pii_flags |= PII_FLAGS_VJC_ON;
  682.         else
  683.         p->pii_flags &= ~PII_FLAGS_VJC_ON;
  684.         mp->b_datap->db_type = M_IOCACK;
  685. #else
  686.         mp->b_datap->db_type = M_IOCNAK;
  687.         i->ioc_error = EINVAL;
  688.         i->ioc_count = 0;
  689. #endif
  690.         qreply(q, mp);
  691.         break;
  692.  
  693.     /*
  694.      * The remaining ioctl's support the options for dialup.
  695.      */
  696.      case SIOCSIFUNIT:
  697.         DLOG2("dp_if: SIFSIFUNIT %d p %x\n",
  698.           *(int *)mp->b_cont->b_rptr, p);
  699.         if (i->ioc_count != sizeof(int)) {
  700.         i->ioc_error = EINVAL;
  701.         goto iocnak;
  702.         }
  703.         if (x = dp_if_unit(q, *(int *)mp->b_cont->b_rptr)) {
  704.         i->ioc_error = x;
  705.         goto iocnak;
  706.         }
  707.         else {
  708.         p = (PII *) q->q_ptr;
  709.         goto iocack;
  710.         }
  711.  
  712.      case SIOCGIFUNIT:    /* get unit number */
  713.      case SIOCGETU:    
  714.         DLOG("dp_if: SIFGIFUNIT %d\n", p->pii_ifnet.if_unit);
  715.         if (mp->b_cont = allocb(sizeof(int), BPRI_MED)) {
  716.         *(int *)mp->b_cont->b_wptr = p->pii_ifnet.if_unit;
  717.         mp->b_cont->b_wptr += i->ioc_count  = sizeof(int);
  718.         mp->b_datap->db_type = M_IOCACK;
  719.         }
  720.         else {
  721.         i->ioc_error = ENOSR;
  722.         i->ioc_count = 0;
  723.         mp->b_datap->db_type = M_IOCNAK;
  724.         }
  725.         qreply(q, mp);
  726.         break;
  727.  
  728.      case SIOCCALLSTAT:    /* Report Call Status */
  729.         DLOG("dp_if: SIFCALLSTAT %d\n", *(char *)mp->b_cont->b_rptr);
  730.         if (i->ioc_count != sizeof(char)) {
  731.         i->ioc_error = EINVAL;
  732. iocnak:
  733.         i->ioc_count = 0;
  734.         mp->b_datap->db_type = M_IOCNAK;
  735.         qreply(q, mp);
  736.         break;
  737.         }
  738.         x = splimp();
  739.         dp_callstat(p, (int)*mp->b_cont->b_rptr);
  740.         splx(x);
  741. iocack:
  742.         mp->b_datap->db_type = M_IOCACK;
  743.         qreply(q, mp);
  744.         break;
  745.  
  746.      case SIOCSDPTIMEO:    /* Set Timeouts */
  747.         if (i->ioc_count != DP_NTIMEOUTS * sizeof(u_long) * DP_NTIMEOUTS) {
  748.         i->ioc_error = EINVAL;
  749.         goto iocnak;
  750.         }
  751.         dp_settimos(p, (u_long *)mp->b_cont->b_rptr, 0, DP_NTIMEOUTS);
  752.         break;
  753.      case SIOCGDPTIMEO:    /* Get Timeouts */
  754.         if (mp->b_cont = allocb(DP_NTIMEOUTS * sizeof(u_long), BPRI_MED)) {
  755.         dp_gettimos(p, (u_long *)mp->b_cont->b_wptr, 0, DP_NTIMEOUTS);
  756.         mp->b_cont->b_wptr += i->ioc_count
  757.                     = DP_NTIMEOUTS * sizeof(u_long);
  758.         mp->b_datap->db_type = M_IOCACK;
  759.         }
  760.         else {
  761.         i->ioc_error = ENOSR;
  762.         i->ioc_count = 0;
  763.         mp->b_datap->db_type = M_IOCNAK;
  764.         }
  765.         qreply(q, mp);
  766.         break;
  767.  
  768.      default:        /* unknown IOCTL call */
  769. passalong:
  770.         putnext(q,mp);    /* pass it along */
  771.     }
  772.     DLOG("dp_if_wput: Pii->flags %x\n", p->pii_flags);
  773.     break;    
  774.      default:
  775.     putnext(q,mp);    /* don't know what to do with this, so send it along*/
  776.     }
  777. }
  778.  
  779. static int
  780. dp_if_wsrv(q)
  781. queue_t    *q;
  782. {
  783.     register mblk_t *mp;
  784.     register PII *p;
  785.  
  786.     p = (PII *) q->q_ptr;
  787.  
  788.     while ((mp = getq(q)) != NULL) {
  789.     /*
  790.      * We can only get M_DATA types into our Queue,
  791.      * due to our Put function
  792.      */
  793.     if (!canput(q->q_next)) {
  794.         putbq(q, mp);
  795.         return;
  796.     }
  797.     putnext(q, mp);    /* just pass it along, nothing to do in this direction */
  798.     }
  799. }
  800.  
  801. static int
  802. dp_if_rput(q, mp)
  803. queue_t *q;
  804. register mblk_t *mp;
  805. {
  806.     register u_char *c;
  807.     register PII *p;
  808.  
  809.     switch (mp->b_datap->db_type) {
  810.      case M_FLUSH:
  811.     if (*mp->b_rptr & FLUSHR)
  812.         flushq(q, FLUSHDATA);
  813.     putnext(q, mp);        /* send it along too */
  814.     break;
  815.  
  816.      case M_DATA:
  817.     putq(q, mp);    /* queue it for my service routine */
  818.     break;
  819.  
  820.      case M_CTL:        /* could be a message from below */
  821.     p = (PII *) q->q_ptr;
  822.     c = (u_char *) mp->b_rptr;
  823.     switch (*c) {
  824.      case IF_INPUT_ERROR:
  825.         p->pii_ifnet.if_ierrors++;
  826.         INCR(sl_ierrors);
  827.         DLOG("dp_if: input error inc to %d\n", p->pii_ifnet.if_ierrors);
  828.         break;
  829.      case IF_OUTPUT_ERROR:
  830.         p->pii_ifnet.if_oerrors++;
  831.         INCR(sl_oerrors);
  832.         DLOG("dp_if: output error inc to %d\n", p->pii_ifnet.if_oerrors);
  833.         break;
  834.      default:
  835.         break;
  836.     }
  837.     freemsg(mp);
  838.     /* putnext(q, mp); */
  839.     break;
  840.      default:
  841.     putnext(q,mp);    /* don't know what to do with this, so send it along*/
  842.     }
  843. }
  844.  
  845. static int
  846. dp_if_rsrv(q)
  847. queue_t    *q;
  848. {
  849.     register mblk_t *mp, *m0;
  850. #ifdef    VJC
  851.     register mblk_t *mvjc;
  852.     unsigned char *cp;
  853.  
  854. #endif
  855.     register PII    *p;
  856.     struct ifnet    **ifp;
  857.     struct ppp_header    *ph;
  858.     struct mbuf    *mb1, *mb2,*mbtail;
  859.     int    len,xlen,count,s;
  860.     u_char    *rptr;
  861.  
  862.     p = (PII *) q->q_ptr;
  863.  
  864.     while ((mp = getq(q)) != NULL) {
  865.     /* we can only get M_DATA types into our Queue, due to our Put function */
  866.     m0 = mp;    /* remember first message block */
  867.     ph = (struct ppp_header *) mp->b_rptr;
  868.     /* assume ppp_header is completely in first block */
  869.     if (mp->b_wptr - mp->b_rptr < sizeof(struct ppp_header)) {
  870.         freemsg(mp);
  871.         p->pii_ifnet.if_ierrors++;
  872.         continue;
  873.     }
  874. #ifdef    VJC
  875.     switch (ntohs(ph->ph_protocol)) {
  876.      case PPP_IP:
  877.         break;
  878.      case PPP_VJC_COMP:
  879.         if (p->pii_flags & PII_FLAGS_VJC_ON) {
  880.         for (xlen=0, mvjc = mp ; mvjc ; mvjc = mvjc->b_cont)
  881.             xlen += (mvjc->b_wptr - mvjc->b_rptr);
  882.         xlen -= sizeof(struct ppp_header);
  883.         if (!(mvjc = allocb(128, BPRI_MED))) {
  884.             /* get a 128 byte buffer for IP header*/
  885.             putbq(q,mp);
  886.             qenable(q);
  887.             return;
  888.         }
  889.         mvjc->b_wptr += 128;
  890.         linkb(mvjc,mp);
  891.         if (!pullupmsg(mvjc,-1)) {
  892.             /* string em all together. ugh what a waste */
  893.             freemsg(mvjc);
  894.             continue;
  895.         }
  896.         cp = mvjc->b_rptr + 128 + sizeof(struct ppp_header);
  897.         m0 = mp = mvjc;
  898.         xlen = sl_uncompress_tcp(&cp,xlen, TYPE_COMPRESSED_TCP, &p->pii_sc_comp);
  899.         if (!xlen) {
  900.             DLOG("dp: sl_uncompress failed on type Compressed",0);
  901.             goto reject;
  902.         }
  903.         mp->b_rptr = cp - sizeof(struct ppp_header);
  904.         ((struct ppp_header *) mp->b_rptr)->ph_protocol = htons(PPP_IP);
  905.         break;
  906.         }
  907.             
  908.      case PPP_VJC_UNCOMP:
  909.         if (p->pii_flags & PII_FLAGS_VJC_ON) {
  910.         cp = (unsigned char *) mp->b_rptr + sizeof(struct ppp_header);
  911.         if (sl_uncompress_tcp(&cp, 1, TYPE_UNCOMPRESSED_TCP, &p->pii_sc_comp)) {
  912.             ((struct ppp_header *) mp->b_rptr)->ph_protocol = htons(PPP_IP);
  913.             break;
  914.         }
  915.         DLOG("dp: sl_uncompress failed on type Uncompresed\n",0);
  916. reject:
  917.         freemsg(mp);
  918.         continue;                
  919.         }
  920.      default:
  921. #endif
  922. #ifndef    VJC
  923.         if (ntohs(ph->ph_protocol) != PPP_IP) {
  924. #endif
  925. #ifdef    DEBUGS
  926.         if (dp_if_debug) {
  927.             switch (ntohs(ph->ph_protocol) & 0xf000) {
  928.              case PPP_LCP:
  929.             DLOG("dp: LCP packet 0x%x\n", ntohs(ph->ph_protocol));
  930.             break;
  931.              case PPP_NCP:
  932.             DLOG("dp: NCP packet 0x%x\n", ntohs(ph->ph_protocol));
  933.             break;
  934.              default:
  935.             DLOG("dp: unknown protocol 0x%x\n",
  936.                  ntohs(ph->ph_protocol));
  937.             }
  938.         }
  939. #endif
  940.         INCR(sl_ipackets);
  941.         if (!canput(q->q_next)) {
  942.             putbq(q, mp);
  943.             return;
  944.         }
  945.         putnext(q,mp);
  946.         p->pii_ifnet.if_ipackets++;
  947.         continue;
  948. #ifndef    VJC
  949.         }
  950. #endif
  951.     }
  952.     len  = 0;
  953.     mb1 = NULL;
  954.     xlen = mp->b_wptr - (rptr = mp->b_rptr);
  955.     while (mp) {
  956.         if (len < 1) {
  957.         MGET(mb2, M_DONTWAIT, MT_DATA);
  958.         if (!mb2) {
  959.             p->pii_ifnet.if_ierrors++;
  960.             putbq(q,m0);
  961.             qenable(q);
  962.             if (mb1)
  963.             m_freem(mb1);    /* discard what we've used already */
  964.             return;
  965.             }            /* if we couldn't get a buffer, put back the message and try later */
  966.             len = MLEN;
  967.             mb2->m_len = 0;
  968.             if (mb1) {
  969.             mbtail->m_next = mb2;
  970.             mbtail = mb2;
  971.             }
  972.             else 
  973.             mbtail = mb1 = mb2;
  974.         }
  975.         count = MIN(xlen, len);
  976.         bcopy((char *) rptr, mtod(mb2, char *) + mb2->m_len, count);
  977. #ifdef    PPP_STATS
  978.         p->pii_stats.sl_ibytes += count;
  979. #endif
  980.         rptr += count;
  981.         len -= count;
  982.         xlen -= count;
  983.         mb2->m_len += count;
  984.         if (!xlen) {    /* move to the next mblk */
  985.         mp = mp->b_cont;
  986.         if (mp)
  987.             xlen = mp->b_wptr - (rptr = mp->b_rptr);
  988.         }
  989.     }
  990. #define    HADJ    (sizeof(struct ppp_header) - sizeof(struct ifnet *))
  991.         /* note, HADJ >= 0 is assumed */
  992.  
  993.     ifp = (struct ifnet **) (mtod(mb1, u_char *) + HADJ);
  994.     *ifp =  &p->pii_ifnet;    /* stick ifnet * in front of packet */
  995.     mb1->m_off += HADJ;
  996.     mb1->m_len -= HADJ;
  997.     freemsg(m0);
  998. #ifdef PPP_SNIT
  999.     if (p->pii_ifnet.if_flags & IFF_PROMISC) {
  1000.         struct mbuf *m = mb1;
  1001.  
  1002.         len = 0;
  1003.         do {
  1004.         len += m->m_len;
  1005.         } while (m = m->m_next);
  1006.         nif.nif_bodylen = len - sizeof(struct ifnet *);
  1007.         mb1->m_off += sizeof(struct ifnet *);
  1008.         snit_intr(&p->pii_ifnet, mb1, &nif);
  1009.         mb1->m_off -= sizeof(struct ifnet *);
  1010.     }
  1011. #endif
  1012.     p->pii_ifnet.if_ipackets++;
  1013.     INCR(sl_ipackets);
  1014. #define    IPADJ    sizeof(struct ppp_header)
  1015.     dp_active(p, (struct ip *)(mtod(mb1, u_char *) + IPADJ),
  1016.           mb1->m_len - IPADJ, 0);
  1017.     s = splimp();
  1018.     if (IF_QFULL(&ipintrq)) {
  1019.         IF_DROP(&ipintrq);
  1020.         p->pii_ifnet.if_ierrors++;
  1021.         m_freem(mb1);
  1022.     }
  1023.     else {
  1024.         IF_ENQUEUE(&ipintrq, mb1);
  1025.         schednetisr(NETISR_IP);
  1026.     }
  1027.     splx(s);
  1028.     }    /* end while */
  1029.  
  1030. }
  1031.  
  1032. /* ifp output procedure */
  1033. int
  1034. dp_output(ifp, m0, dst)
  1035.     struct ifnet *ifp;
  1036.     struct mbuf *m0;
  1037.     struct sockaddr *dst;
  1038. {
  1039.     register PII    *p = &dupii[ifp->if_unit];
  1040.     struct mbuf    *m;
  1041.     int    error, s;
  1042.     u_short protocol;
  1043.     
  1044.     DLOG2("dp_output: state %s flags %x\n", dus_str[p->pii_dustate], p->pii_flags);
  1045.  
  1046.     error = 0;
  1047.     if (!(ifp->if_flags & IFF_RUNNING)) {
  1048.     error = ENETDOWN;
  1049.     goto getout;
  1050.     }
  1051.  
  1052.     switch (p->pii_dustate) {
  1053.      case PII_DPS_ACTIVE:
  1054.     /*
  1055.      * The easy case..
  1056.      * The line is active and we are set..
  1057.      */
  1058.     break;
  1059.  
  1060.      case PII_DPS_DOWN:
  1061.      case PII_DPS_FAILCALL:
  1062.     /*
  1063.      * If the net is marked down or we have recently failed in calling,
  1064.      * might as well give up now.
  1065.      */
  1066.     DLOGSTATE("dp_output: NETDOWN %s\n");
  1067.     error = ENETDOWN;
  1068.     goto getout;
  1069.  
  1070.      case PII_DPS_WAITING:
  1071.     /*
  1072.      * If we are waiting on a call to go through, queue this packet
  1073.      * and don't signal any error. 
  1074.      */
  1075.     DLOGFLAGS("dp_output: DPS_WAITING %x %x\n");
  1076.     goto qpacket;
  1077.  
  1078.      case PII_DPS_DISCON:
  1079.     /*
  1080.      * If not already talking on the line,
  1081.      * try to initiate a call.
  1082.      */
  1083.     switch (dst->sa_family) {
  1084. #ifdef    INET
  1085.      case AF_INET:
  1086.         if (duipreq(m0, dst, ifp)) {
  1087.         DLOGFLAGS("dp_output: duipreq failed %x %x\n");
  1088.         error = ENETDOWN;
  1089.         goto getout;
  1090.         }
  1091.         break;
  1092. #endif
  1093.      default:
  1094.         /*
  1095.          * Punt for now.
  1096.          */
  1097.         DLOGFLAGS("dp_output: DISCON bad family %x %x\n");
  1098.         error = ENETDOWN;
  1099.         goto getout;
  1100.     }
  1101.     dp_state(p, PII_DPS_WAITING);
  1102.     DLOGFLAGS("dp_output: duipreq in progress %x %x\n");
  1103.     goto qpacket;
  1104.  
  1105.      default:
  1106.     DLOG("dp_output: unknown state %d\n", p->pii_dustate);
  1107.     break;
  1108.     }
  1109.  
  1110. qpacket:
  1111.     switch (dst->sa_family) {
  1112. #ifdef    INET
  1113.      case AF_INET:
  1114. #ifdef PPP_SNIT
  1115.     if (ifp->if_flags & IFF_PROMISC) {
  1116.         struct mbuf *m = m0;
  1117.         int len = 0;
  1118.         do {
  1119.         len += m->m_len;
  1120.         } while (m = m->m_next);
  1121.         nif.nif_bodylen = len;
  1122.         snit_intr(ifp, m0, &nif);
  1123.     }
  1124. #endif
  1125.     protocol = PPP_IP;
  1126.     break;
  1127. #endif
  1128. #ifdef    NS
  1129.      case AF_NS:
  1130.     protocol = PPP_XNS;
  1131.     break;
  1132. #endif
  1133.      default:
  1134.     printf("dp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
  1135.     error = EAFNOSUPPORT;
  1136.     goto getout;
  1137.     }
  1138.     /*
  1139.      * Prepend the protocol to this packet.
  1140.      */
  1141.     if (m0->m_off > MMAXOFF || MMINOFF + sizeof(protocol) > m0->m_off) {
  1142.     m = m_get(M_DONTWAIT, MT_HEADER);
  1143.     if (m == 0) {
  1144.         error = ENOBUFS;
  1145.         goto getout;
  1146.     }
  1147.     m->m_next = m0;
  1148.     m->m_len = sizeof(protocol);
  1149.     m0 = m;
  1150.     }
  1151.     else {
  1152.     m0->m_off -= sizeof(protocol);
  1153.     m0->m_len += sizeof(protocol);
  1154.     }
  1155.     bcopy((caddr_t)&protocol, mtod(m0, caddr_t), sizeof(protocol));
  1156.  
  1157.     s = splimp();
  1158.     if (IF_QFULL(&ifp->if_snd))
  1159.     IF_DROP(&ifp->if_snd);
  1160.     IF_ENQUEUE(&ifp->if_snd, m0);
  1161.     error = dp_start(p);
  1162.     splx(s);
  1163.     if (error) {
  1164.     INCR(sl_oerrors);
  1165.     p->pii_ifnet.if_oerrors++;
  1166.     }
  1167.     return(error);        /* gads, streams are great */
  1168. getout:
  1169.     if (m0)
  1170.     m_freem(m0);
  1171.     if (error) {
  1172.     INCR(sl_oerrors);
  1173.     p->pii_ifnet.if_oerrors++;
  1174.     }
  1175.     return(error);        /* gads, streams are great */
  1176. }
  1177.  
  1178. static int
  1179. dp_start(p)
  1180.     register PII    *p;
  1181. {
  1182.     struct mbuf    *m0, *m1;
  1183.     int len;
  1184.     u_short    protocol;
  1185.     mblk_t    *mp;
  1186.     int s;
  1187. #ifdef    VJC
  1188.     u_char    type;
  1189. #endif
  1190.  
  1191.     while (p->pii_ifnet.if_snd.ifq_head && p->pii_writeq &&
  1192.        (p->pii_dustate == PII_DPS_ACTIVE)) {
  1193.     IF_DEQUEUE(&p->pii_ifnet.if_snd, m0);
  1194.     protocol = *mtod(m0, u_short *);
  1195.     bcopy(mtod(m0, caddr_t), (caddr_t)&protocol, sizeof(protocol));
  1196.     m0->m_off += sizeof(protocol);
  1197.     m0->m_len -= sizeof(protocol);
  1198.     if (m0->m_len == 0)
  1199.         m0 = m_free(m0);
  1200. #ifdef    VJC
  1201.     if ((protocol == PPP_IP) && (p->pii_flags & PII_FLAGS_VJC_ON)) {
  1202.         register struct ip *ip;
  1203.         if ((m0->m_off > MMAXOFF || m0->m_len < sizeof(struct ip)) &&
  1204.         (m0 = m_pullup(m0, sizeof(struct ip))) == 0) {
  1205.         INCR(sl_oerrors);
  1206.         p->pii_ifnet.if_oerrors++;
  1207.         return ENOBUFS;
  1208.         }
  1209.  
  1210.         ip = mtod(m0, struct ip *);
  1211.         dp_active(p, ip, m0->m_len, 1);
  1212.         if (ip->ip_p == IPPROTO_TCP) {
  1213.         type = sl_compress_tcp(m0, ip, &p->pii_sc_comp, 1);
  1214.         switch (type) {
  1215.          case TYPE_UNCOMPRESSED_TCP:
  1216.             protocol = PPP_VJC_UNCOMP;
  1217.             break;
  1218.          case TYPE_COMPRESSED_TCP:
  1219.             protocol = PPP_VJC_COMP;
  1220.             break;    
  1221.         }
  1222.         }
  1223.     }
  1224. #endif
  1225.     len = 0;
  1226.     for (m1 = m0; m1; m1 = m1->m_next) 
  1227.         len += m1->m_len;
  1228.     if (!(p->pii_flags & PII_FLAGS_COMPAC))
  1229.         len += 2;    /* if we are not compac, then need 2 extra bytes */
  1230.     if (!(p->pii_flags & PII_FLAGS_COMPPROT))
  1231.         len++;
  1232.     len++;
  1233.     /*
  1234.      * We never need to check the actual protocol,  since
  1235.      * its always either PPP_IP, PPP_VJC_*, or PPP_XNS
  1236.      */
  1237.     if (!(mp = allocb(len, BPRI_LO))) {
  1238.         INCR(sl_oerrors);
  1239.         p->pii_ifnet.if_oerrors++;
  1240.         m_freem(m0);
  1241.         return ENOBUFS;
  1242.     }
  1243. #ifdef    PPP_STATS
  1244.     p->pii_stats.sl_obytes += len;
  1245. #endif
  1246.     if (!(p->pii_flags & PII_FLAGS_COMPAC)) {
  1247.         *mp->b_wptr++ = PPP_ALLSTATIONS;
  1248.         *mp->b_wptr++ = PPP_UI;
  1249.     }
  1250.     if (!(p->pii_flags & PII_FLAGS_COMPPROT))
  1251.         *mp->b_wptr++ = 0;
  1252.     *mp->b_wptr++ = protocol & 0xff;
  1253.     for (m1 = m0; m1; m1 = m1->m_next) {        /* copy all data */
  1254.         bcopy(mtod(m1, char *), (char *) mp->b_wptr, m1->m_len);
  1255.         mp->b_wptr += m1->m_len;
  1256.     }
  1257.     m_freem(m0);
  1258.  
  1259.     s = splstr();
  1260.     putq(p->pii_writeq, mp);
  1261.     splx(s);
  1262.  
  1263.     p->pii_ifnet.if_opackets++;
  1264.     INCR(sl_opackets);
  1265.     }
  1266.     return 0;
  1267. }
  1268.  
  1269. /*
  1270.  * if_ ioctl requests 
  1271. */
  1272. dp_ioctl(ifp, cmd, data)
  1273. register struct ifnet *ifp;
  1274. int    cmd;
  1275. caddr_t    data;
  1276. {
  1277.     register struct ifaddr *ifa = (struct ifaddr *) data;
  1278.     register struct ifreq *ifr = (struct ifreq *) data;
  1279.     int    s = splimp(), error = 0;
  1280.  
  1281.     if (ifa == NULL ) {
  1282.     splx(s);
  1283.     return(EFAULT);
  1284.     }
  1285.  
  1286.     switch (cmd) {
  1287.      case SIOCSIFFLAGS:
  1288.     if (!suser()) {
  1289.         error = EPERM;
  1290.         break;
  1291.     }
  1292.     ifp->if_flags &= (IFF_CANTCHANGE);    /* clear the flags that can be cleared */
  1293.     ifp->if_flags |= (ifr->ifr_flags & ~IFF_CANTCHANGE); /* or in the flags that can
  1294.                                 be changed */
  1295.     dp_init(ifp->if_unit);
  1296.     break;
  1297.      case SIOCGIFFLAGS:
  1298.     ifr->ifr_flags = ifp->if_flags;
  1299.     break;
  1300.      case SIOCSIFADDR:
  1301.     if (ifa->ifa_addr.sa_family != AF_INET) 
  1302.         error = EAFNOSUPPORT;
  1303.     break;
  1304.      case SIOCSIFDSTADDR:
  1305.     if (ifa->ifa_addr.sa_family != AF_INET)
  1306.         error = EAFNOSUPPORT;
  1307.     break;
  1308.  
  1309. #ifndef    ifr_mtu
  1310. #define    ifr_mtu    ifr_metric
  1311. #endif
  1312.      case SIOCSIFMTU:
  1313.     if (!suser()) {
  1314.         error = EPERM;
  1315.         break;
  1316.     }
  1317.     if (ifr->ifr_mtu >
  1318.         (4096 - (sizeof(struct ppp_header) + sizeof(u_short)))) {
  1319.         error = EINVAL;
  1320.         break;
  1321.     }
  1322.     ifp->if_mtu = ifr->ifr_mtu;
  1323.     break;
  1324.      case SIOCGIFMTU:
  1325.     ifr->ifr_mtu = ifp->if_mtu;
  1326.     break;
  1327.  
  1328.      case SIOCICALLSTAT:
  1329.     dp_callstat(&dupii[ifp->if_unit], ifr->ifr_data[0]);
  1330.     break;
  1331.  
  1332.      case SIOCSDPIATIMEO:    /* Set Activity Timeouts */
  1333.     dp_settimos(&dupii[ifp->if_unit], (u_long *)ifr->ifr_data,
  1334.             DP_ATIMEOUTS, DP_NATIMEOUTS);
  1335.     break;
  1336.      case SIOCGDPIATIMEO:    /* Get Activity Timeouts */
  1337.     dp_gettimos(&dupii[ifp->if_unit], (u_long *)ifr->ifr_data,
  1338.             DP_ATIMEOUTS, DP_NATIMEOUTS);
  1339.     break;
  1340.  
  1341.      case SIOCSDPICTIMEO:    /* Set Call Timeouts */
  1342.     dp_settimos(&dupii[ifp->if_unit], (u_long *)ifr->ifr_data,
  1343.             DP_CTIMEOUTS, DP_NCTIMEOUTS);
  1344.     break;
  1345.      case SIOCGDPICTIMEO:    /* Get Call Timeouts */
  1346.     dp_gettimos(&dupii[ifp->if_unit], (u_long *)ifr->ifr_data,
  1347.             DP_CTIMEOUTS, DP_NCTIMEOUTS);
  1348.     break;
  1349.  
  1350.      case SIOCGDPIISTATS:    /* Get Input Stats */
  1351.     dp_gstats(&dupii[ifp->if_unit], (u_int *)ifr->ifr_data, 0);
  1352.     break;
  1353.  
  1354.      case SIOCGDPIOSTATS:    /* Get Output Stats */
  1355.     dp_gstats(&dupii[ifp->if_unit], (u_int *)ifr->ifr_data, 1);
  1356.     break;
  1357.  
  1358.      default:
  1359.     error = EINVAL;
  1360.     break;
  1361.     }
  1362.     splx(s);
  1363.     return(error);
  1364. }
  1365.  
  1366. static
  1367. dp_gstats(p, stats, out)
  1368. register PII *p;
  1369. register u_int *stats;
  1370. int out;
  1371. {
  1372. #ifdef    PPP_STATS
  1373.     struct slipstat *ss = &p->pii_stats;
  1374.     if (out) {
  1375.     stats[0] = ss->sl_obytes;
  1376.     stats[1] = ss->sl_opackets;
  1377.     stats[2] = ss->sl_oerrors;
  1378.     }
  1379.     else {
  1380.     stats[0] = ss->sl_ibytes;
  1381.     stats[1] = ss->sl_ipackets;
  1382.     stats[2] = ss->sl_ierrors;
  1383.     }
  1384. #endif    PPP_STATS
  1385. }
  1386.  
  1387. static
  1388. dp_settimos(p, to, t0, nt)
  1389. register PII *p;
  1390. register u_long *to;
  1391. register int t0, nt;
  1392. {
  1393.     register int t;
  1394.     for (t = 0 ; t < nt ; t++)
  1395.     switch (to[t]) {
  1396.      case DP_DEF_TIMEOUT:
  1397.         break;
  1398.      case DP_NO_TIMEOUT:
  1399.         p->pii_timo[t0 + t] = DP_NO_TIMEOUT;
  1400.         break;
  1401.      default:
  1402.         p->pii_timo[t0 + t] = to[t] / DP_HZ;
  1403.         break;
  1404.     }
  1405.     /*
  1406.      * If we are using certain timeouts, do extra processing
  1407.      * on each packet.
  1408.      */
  1409.     if (p->pii_timo[DP_CTIMEO] == DP_NO_TIMEOUT &&
  1410.     p->pii_timo[DP_UTIMEO] == DP_NO_TIMEOUT)
  1411.     p->pii_flags &= ~PII_FLAGS_ACTIVE;
  1412.     else
  1413.     p->pii_flags |=  PII_FLAGS_ACTIVE;
  1414.  
  1415.     DLOG5("dp_settimos: t0 %d nt %d - %d %d %d\n", t0, nt,
  1416.       to[t0], to[t0+1], to[t0+2]);
  1417.     DLOG5("dp_settimos: timeouts %d %d %d %d %d\n", p->pii_timo[0] * DP_HZ,
  1418.       p->pii_timo[1] * DP_HZ, p->pii_timo[2] * DP_HZ,
  1419.       p->pii_timo[3] * DP_HZ, p->pii_timo[4] * DP_HZ);
  1420. }
  1421.  
  1422. static
  1423. dp_gettimos(p, to, t0, nt)
  1424. register PII *p;
  1425. register u_long *to;
  1426. register int t0, nt;
  1427. {
  1428.     register int t;
  1429.     for (t = 0 ; t < nt ; t++)
  1430.     to[t] = p->pii_timo[t0 + t] * DP_HZ;
  1431.     DLOG5("dp_gettimos: timeouts %d %d %d %d %d\n", p->pii_timo[0] * DP_HZ,
  1432.       p->pii_timo[1] * DP_HZ, p->pii_timo[2] * DP_HZ,
  1433.       p->pii_timo[3] * DP_HZ, p->pii_timo[4] * DP_HZ);
  1434. }
  1435.  
  1436. static
  1437. dp_state(p, dustate)
  1438. register PII *p;
  1439. register int dustate;
  1440. {
  1441.     if (p->pii_dustate == dustate)
  1442.     return;
  1443.     p->pii_dustate = dustate;
  1444.     p->pii_timer = p->pii_timo[p->pii_dustate];
  1445.     p->pii_ftimer = DP_NO_TIMEOUT;
  1446.     p->pii_ifnet.if_timer = (p->pii_timer > 0 || p->pii_ftimer > 0) ? DP_HZ : 0;
  1447. #ifdef    DEBUGS
  1448.     if (dp_if_debug || dp_ftimo_debug)
  1449.     log(LOG_INFO, "dp_state: %s %d %d (%d)\n", dus_str[dustate],
  1450.         p->pii_timer, p->pii_ftimer, p->pii_ifnet.if_timer);
  1451. #endif
  1452. }
  1453.  
  1454. static void
  1455. dp_event(p, timer)
  1456. register PII *p;
  1457. register int timer;
  1458. {
  1459.     register int timo;
  1460.     p->pii_timer = p->pii_timo[p->pii_dustate];
  1461.     switch (timer) {
  1462. #if    0
  1463.      case DP_ATIMEO:
  1464.     p->pii_ftimer = DP_NO_TIMEOUT;
  1465.     break;
  1466. #endif
  1467.      case DP_UTIMEO:
  1468.      case DP_CTIMEO:
  1469.     if ((timo = p->pii_timo[timer]) >= 0 && timo > p->pii_ftimer)
  1470.         p->pii_ftimer = timo;
  1471.     break;
  1472.     }
  1473.     p->pii_ifnet.if_timer = (p->pii_timer > 0 || p->pii_ftimer > 0) ? DP_HZ : 0;
  1474. #ifdef    DEBUGS
  1475.     if (dp_if_debug || dp_ftimo_debug)
  1476.     log(LOG_INFO, "dp_event: %s/%s %d %d (%d)\n",
  1477.         dus_str[p->pii_dustate], dus_str[timer],
  1478.         p->pii_timer, p->pii_ftimer, p->pii_ifnet.if_timer);
  1479. #endif
  1480. }
  1481.  
  1482. /*
  1483.  * dp_timer() provides for the following state transitions on timeout..
  1484.  *
  1485.  * State    Status         New State
  1486.  * FAILCALL    TIMEOUT        DISCON        (can try calling again)
  1487.  * ACTIVE    TIMEOUT        DISCON        (inactivity timeout)
  1488.  * WAITING    TIMEOUT        FAILCALL    (dialer is taking too long)
  1489.  */
  1490. static int
  1491. dp_timer(unit)
  1492. int unit;
  1493. {
  1494.     register PII *p = &dupii[unit];
  1495.     queue_t *q = p->pii_writeq;
  1496.     register int s;
  1497.  
  1498.  
  1499.     /* just being cautious by setting up the interrupt priority */
  1500.     s = splimp();
  1501.  
  1502.     /*
  1503.      * Count down the timers.
  1504.      */
  1505.     if (p->pii_timer > 0)
  1506.     p->pii_timer--;
  1507.     if (p->pii_ftimer > 0)
  1508.     p->pii_ftimer--;
  1509.  
  1510. #ifdef    DEBUGS
  1511.     if (dp_if_debug || dp_ftimo_debug)
  1512.     log(LOG_INFO, "dp_timer: before %s %d %d\n",
  1513.         dus_str[p->pii_dustate], p->pii_timer, p->pii_ftimer);
  1514. #endif
  1515.     /*
  1516.      * Ignore the fast timer expiration if we have active connections.
  1517.      */
  1518.     if (p->pii_ftimer == 0 && p->pii_active.da_nactive) {
  1519.     DLOGSTATE("dp_timer: fast timer ignored (%s)\n");
  1520. #ifdef    DEBUGS
  1521.     if (dp_if_debug || dp_ftimo_debug)
  1522.         log(LOG_INFO, "dp_timer: fast timer ignored (%s)\n",
  1523.             dus_str[p->pii_dustate]);
  1524. #endif
  1525.     p->pii_ftimer = DP_NO_TIMEOUT;
  1526.     }
  1527.  
  1528.     /*
  1529.      * If we are still counting down, get out of here..
  1530.      */
  1531.     if (p->pii_timer && p->pii_ftimer) {
  1532.     /* Reset the interface timer, and return */
  1533.     p->pii_ifnet.if_timer = DP_HZ;
  1534.     splx(s);
  1535.     return;
  1536.     }
  1537.  
  1538. #ifdef    DEBUGS
  1539.     if (dp_if_debug || dp_ftimo_debug)
  1540.     log(LOG_INFO, "dp_timer: %stimer expired, state = %s\n",
  1541.         p->pii_ftimer == 0 ? "fast " : "", dus_str[p->pii_dustate]);
  1542. #endif
  1543.     /*
  1544.      * One of the timers counted down to zero..
  1545.      */
  1546.     switch (p->pii_dustate) {
  1547.      case PII_DPS_DOWN:
  1548.      case PII_DPS_DISCON:
  1549.     /*
  1550.      * Do nothing....
  1551.      */
  1552.     break;
  1553.      case PII_DPS_WAITING:
  1554.     /*
  1555.      * Assume that the dialup program hung, so assume a failed call.
  1556.      */
  1557.     dp_state(p, PII_DPS_FAILCALL);
  1558.     dp_flush(p, q);
  1559.     DLOG("dp_timer: unit %d - we never had a line.\n", unit);
  1560.     break;
  1561.  
  1562.      case PII_DPS_ACTIVE:
  1563.     /*
  1564.      * Shut down the line for now by sending a signal to the PPP process.
  1565.      */
  1566.     dp_state(p, PII_DPS_DISCON);
  1567.     DLOG("dp_timer: sending SIGTERM to PPP process\n", unit);
  1568.     putctl1(RD(q), M_PCSIG, SIGTERM);
  1569.     break;
  1570.  
  1571.      case PII_DPS_FAILCALL:
  1572.     /*
  1573.      * Reenable the line for call attempts.
  1574.      */
  1575.     dp_state(p, PII_DPS_DISCON);
  1576.     break;
  1577.  
  1578.      default:
  1579.     DLOG("dp_timer: unknown state %d\n", p->pii_dustate);
  1580.     break;
  1581.     }
  1582.     splx(s);
  1583.     DLOGSTATE("dp_timer: after %s\n");
  1584. }
  1585.  
  1586. static void
  1587. dp_active_tinit(tab)
  1588. struct dp_ctab *tab;
  1589. {
  1590.     register struct dp_conv *conv = tab->dt_conv;
  1591.     register int i;
  1592.     for (i = MAX_ACTIVE - 1; i > 0; --i)
  1593.     conv[i].dc_next = &conv[i - 1];
  1594.     conv[0].dc_next = &conv[MAX_ACTIVE - 1];
  1595.     tab->dt_last = &conv[0];
  1596. }
  1597.  
  1598. static void
  1599. dp_active_init(act)
  1600. struct dp_active *act;
  1601. {
  1602.     bzero((char *)act, sizeof(*act));
  1603.     dp_active_tinit(&act->da_ttab);
  1604.     dp_active_tinit(&act->da_rtab);
  1605. }
  1606.  
  1607.  
  1608. static void dp_rstactive();
  1609.  
  1610. static void
  1611. dp_active(p, ip, len, xmit)
  1612. register PII *p;
  1613. register struct ip *ip;
  1614. int len;
  1615. int xmit;
  1616. {
  1617.     register struct dp_active *act;
  1618.     register struct dp_ctab *tab;
  1619.     register struct dp_conv *conv;
  1620.     register struct tcphdr *th;
  1621.     register u_int hlen;
  1622.  
  1623.     if (!(p->pii_flags & PII_FLAGS_ACTIVE)) {
  1624.     dp_event(p, DP_ATIMEO);
  1625.     return;
  1626.     }
  1627. #ifdef    DEBUGS
  1628.     act = &p->pii_active;
  1629. #endif
  1630.     /*
  1631.      * Don't bother with fragments.
  1632.      */
  1633.     if (len < sizeof(struct ip) || ip->ip_off & htons(0x3fff)) {
  1634.     DLOG_ACTIVE("len");
  1635.     return;
  1636.     }
  1637.  
  1638.     /*
  1639.      * Account for non-tcp traffic.
  1640.      */
  1641.     if (ip->ip_p != IPPROTO_TCP) {
  1642.     DLOG_ACTIVE("nontcp");
  1643.     dp_event(p, DP_UTIMEO);
  1644.     return;
  1645.     }
  1646.  
  1647.     /*
  1648.      * This shouldn't happen, but if it does,
  1649.      * Make sure we have enough of the TCP header to be interesting..
  1650.      */
  1651.     hlen = ip->ip_hl << 2;
  1652.     if (len < hlen + sizeof(struct tcphdr)) {
  1653.     DLOG_ACTIVE("len2");
  1654.     return;
  1655.     }
  1656.  
  1657.     /*
  1658.      * Look for the conversation in our table.
  1659.      * Check if it is the most recently used (it probably is).
  1660.      * If not, search the table in MRU order.
  1661.      */
  1662. #ifndef    DEBUGS
  1663.     act = &p->pii_active;
  1664. #endif
  1665.     th = (struct tcphdr *)&((char *)ip)[hlen];
  1666.     tab = xmit ? &act->da_ttab : &act->da_rtab;
  1667.     conv = tab->dt_last->dc_next;
  1668.     act->da_lookups++;
  1669.  
  1670.     if (ip->ip_src.s_addr != conv->dc_ip_src.s_addr ||
  1671.     ip->ip_dst.s_addr != conv->dc_ip_dst.s_addr ||
  1672.     *(int *)th != *((int *)&conv->dc_th_sport)) {
  1673.     /*
  1674.      * Not the most recently used conversation, look through the
  1675.      * circularly linked list.
  1676.      */
  1677.     register struct dp_conv *lconv,
  1678.                 *last = tab->dt_last;
  1679.  
  1680.     act->da_misses++;
  1681.     do {
  1682.         lconv = conv;
  1683.         conv = conv->dc_next;
  1684.         if (ip->ip_src.s_addr == conv->dc_ip_src.s_addr &&
  1685.         ip->ip_dst.s_addr == conv->dc_ip_dst.s_addr &&
  1686.         *(int *)th == *((int *)&conv->dc_th_sport)) {
  1687.         /*
  1688.          * This conversation is in the table somewhere.
  1689.          * Move it to the front of the list.
  1690.          */
  1691.         if (conv == last)
  1692.             tab->dt_last = lconv;
  1693.         else {
  1694.             lconv->dc_next = conv->dc_next;
  1695.             conv->dc_next = last->dc_next;
  1696.             last->dc_next = conv;
  1697.         }
  1698.         goto intable;
  1699.         }
  1700.     } while (conv != last);
  1701.  
  1702.     /*
  1703.      * If the LRU conversation is active, and we have at least one
  1704.      * inactive conversation, move the LRU inactive connection to the
  1705.      * LRU slot.
  1706.      *
  1707.      * It was considered best to scan the table again here to make
  1708.      * the first table scan quicker since it is executed more frequently.
  1709.      */
  1710.     if (conv->dc_flags & DC_ACTIVE) {
  1711.         register struct dp_conv *linact = (struct dp_conv *)0;
  1712.  
  1713.         lconv = tab->dt_last;
  1714.         conv = lconv->dc_next;
  1715.         if (!(conv->dc_flags & DC_ACTIVE))
  1716.         linact = lconv;
  1717.         do {
  1718.         lconv = conv;
  1719.         conv = conv->dc_next;
  1720.         if (!(conv->dc_flags & DC_ACTIVE))
  1721.             linact = lconv;
  1722.         } while (conv != last);
  1723.         if (linact) {
  1724.         conv = linact->dc_next;
  1725.         lconv = last;
  1726.  
  1727.         linact->dc_next = conv->dc_next;
  1728.         conv->dc_next = last->dc_next;
  1729.         last->dc_next = conv;
  1730.         }
  1731.     }
  1732. #if    1
  1733.     /*
  1734.      * With this #ifdef'ed out, the fast timeout will be effectively
  1735.      * disabled when more than MAX_ACTIVE (16) conversations are in effect.
  1736.      * With this included, MAX_ACTIVE fast connects and disconnects will
  1737.      * cause a fast timeout even if there are active conversations.
  1738.      */
  1739.     if (conv->dc_flags & DC_ACTIVE)
  1740.         act->da_nactive--;
  1741. #endif
  1742.     /*
  1743.      * This conversation is not in our table.
  1744.      * Create an entry for it in the least recently used slot.
  1745.      */
  1746.     tab->dt_last = lconv;
  1747.     conv->dc_ip_src.s_addr = ip->ip_src.s_addr;
  1748.     conv->dc_ip_dst.s_addr = ip->ip_dst.s_addr;
  1749.     *((int *)&conv->dc_th_sport) = *(int *)th;
  1750.     conv->dc_flags = DC_ACTIVE;
  1751.     act->da_nactive++;
  1752.     DLOG_ACTIVE("NEW");
  1753.     }
  1754.     
  1755. intable:
  1756.     if (conv->dc_flags & DC_ACTIVE) {
  1757.     if (th->th_flags & (TH_FIN|TH_RST)) {
  1758.         /*
  1759.          * Conversation shutting down
  1760.          */
  1761.         conv->dc_flags &= ~DC_ACTIVE;
  1762.         act->da_nactive--;
  1763.         DLOG_ACTIVE((th->th_flags & TH_FIN) ? "FIN" : "RST");
  1764.     }
  1765.     }
  1766.     else
  1767.     if (th->th_flags & TH_SYN) {
  1768.         /*
  1769.          * Conversation (re)starting
  1770.          */
  1771.         conv->dc_flags |= DC_ACTIVE;
  1772.         act->da_nactive++;
  1773.         DLOG_ACTIVE("SYN");
  1774.     }
  1775.     dp_event(p, act->da_nactive ? DP_ATIMEO : DP_CTIMEO);
  1776.     /*
  1777.      * On a reset, do special processing.
  1778.      */
  1779.     if (th->th_flags & TH_RST)
  1780.     dp_rstactive(p, ip, len, xmit);
  1781. }
  1782.  
  1783. /*
  1784.  * A reset affects both halves of a conversation.  Here, when a RST
  1785.  * happens on half of a conversation, we fake a FIN for the other half
  1786.  * since a TCP will never respond to a RST..
  1787.  */
  1788. static void
  1789. dp_rstactive(p, ip, len, xmit)
  1790. register PII *p;
  1791. register struct ip *ip;
  1792. int len;
  1793. int xmit;
  1794. {
  1795. #define    HDR_SLOP    44
  1796.     char revip[sizeof(struct ip)+sizeof(struct tcphdr)+HDR_SLOP];
  1797.     register struct ip *ip2 = (struct ip *)revip;
  1798.     register struct tcphdr *th, *th2;
  1799.     register u_int hlen = ip->ip_hl << 2;
  1800.  
  1801.     if (hlen + sizeof(struct tcphdr) > sizeof(revip))
  1802.     return;
  1803.     th  = (struct tcphdr *)&((char *)ip)[hlen];
  1804.     th2 = (struct tcphdr *)&((char *)ip2)[hlen];
  1805.     bcopy((char *)ip, (char *)ip2, hlen);
  1806.     th2->th_flags = (th->th_flags & ~TH_RST) | TH_FIN;
  1807.     ip2->ip_src = ip->ip_dst;
  1808.     ip2->ip_dst = ip->ip_src;
  1809.     th2->th_sport = th->th_dport;
  1810.     th2->th_dport = th->th_sport;
  1811.     dp_active(p, ip2, hlen + sizeof(struct tcphdr), !xmit);
  1812. }
  1813.  
  1814. /*
  1815.  * This code implements the streams device for communicating connect requests
  1816.  * to user-land.  This was formerly in a sepearate file (ppp_dial.c),
  1817.  * but in the expectation of future updates to allow loadable modules,
  1818.  * these two files were merged since one file calls a function in the
  1819.  * other file.  Loadable modules are apparently picky about that and there
  1820.  * is no way to get around the function call..
  1821.  */
  1822. #undef    DLOG
  1823. #ifdef    DEBUGS
  1824. #define    DLOG(s,a)    if(ppp_dial_debug) log(LOG_INFO, s, a)
  1825. int    ppp_dial_debug=0;
  1826. #else
  1827. #define    DLOG(s,a)    {}
  1828. #endif
  1829.  
  1830. static    int    ppp_dial_open(), ppp_dial_close(), ppp_dial_rsrv(),
  1831.         ppp_dial_wput();
  1832.  
  1833. static     struct    module_info    ppp_dial_minfo = {
  1834.     0xbae,"pppdial",0, INFPSZ, DP_HIWAT, DP_LOWAT
  1835. };
  1836.  
  1837. static    struct    qinit    ppp_dial_rinit = {
  1838.     NULL, ppp_dial_rsrv, ppp_dial_open, ppp_dial_close, NULL,
  1839.     &ppp_dial_minfo, NULL
  1840. };
  1841. static    struct    qinit    ppp_dial_winit = {
  1842.     ppp_dial_wput, NULL, NULL, NULL, NULL,
  1843.     &ppp_dial_minfo, NULL
  1844. };
  1845. struct    streamtab    ppp_dialinfo = {
  1846.     &ppp_dial_rinit, &ppp_dial_winit, NULL, NULL, NULL
  1847. };
  1848.  
  1849. queue_t *req_q;
  1850.  
  1851. static int
  1852. ppp_dial_open(q, dev, flag, sflag)
  1853. queue_t    *q;
  1854. dev_t    dev;
  1855. int    flag,
  1856.     sflag;
  1857.  
  1858. {
  1859.     if (!suser()) {
  1860.     u.u_error = EPERM;
  1861.     return(OPENFAIL);
  1862.     }
  1863.     /*
  1864.      * Insure this is a normal driver open..
  1865.      */
  1866.     if (sflag)
  1867.     return (OPENFAIL);
  1868.  
  1869.     /*
  1870.      * Insure exclusive access.
  1871.      */
  1872.     if (q->q_ptr) {
  1873.     u.u_error = EBUSY;
  1874.     return(OPENFAIL);
  1875.     }
  1876.  
  1877.     q->q_ptr = "ppp daemon running";
  1878.     req_q = q;
  1879.     DLOG("ppp_dial%d: open\n", minor(dev));
  1880.     return dev;
  1881. }
  1882.  
  1883. static int
  1884. ppp_dial_close(q)
  1885. queue_t    *q;            /* queue info */
  1886. {
  1887.     req_q = (queue_t *)0;
  1888.     q->q_ptr = (char *)0;
  1889.     DLOG("ppp_dial: close\n", 0);
  1890.     return 0;
  1891. }
  1892.  
  1893.  
  1894. static int
  1895. ppp_dial_wput(q, mp)
  1896. queue_t  *q;
  1897. register mblk_t *mp;
  1898. {
  1899.     switch (mp->b_datap->db_type) {
  1900.      case  M_FLUSH:
  1901.     if (*mp->b_rptr & FLUSHW)
  1902.         flushq(q, FLUSHDATA);
  1903.     if (*mp->b_rptr & FLUSHR) {
  1904.         flushq(RD(q), FLUSHDATA);
  1905.         *mp->b_rptr &= ~FLUSHW;
  1906.         qreply(q, mp);
  1907.     }
  1908.     else 
  1909.         freemsg(mp);
  1910.     break;
  1911.      case M_DATA:
  1912.      case M_IOCTL:
  1913.      default:
  1914.     /*
  1915.      * For now, do nothing with stuff written to the stream.
  1916.      * Later on, support returning status of dial
  1917.      * operations.
  1918.      */
  1919.     freemsg(mp);
  1920.     break;
  1921.     }
  1922.  
  1923. }
  1924.  
  1925. static int
  1926. ppp_dial_rsrv(q)
  1927. queue_t *q;
  1928. {
  1929.     register mblk_t *mp;
  1930.  
  1931.     while ((mp = getq(q)) != NULL) {
  1932.     switch (mp->b_datap->db_type) {
  1933.      case M_FLUSH:
  1934.         if(*mp->b_rptr & FLUSHR)
  1935.         flushq(q, FLUSHDATA);
  1936.         DLOG("ppp_dial_rsrv: M_FLUSH\n", 0);
  1937.         putnext(q, mp);        /* send it along too */
  1938.         break;
  1939.      case M_DATA:
  1940.         if (!canput(q->q_next)) {
  1941. #define    DISCARD_OLDEST
  1942. #ifdef    DISCARD_OLDEST
  1943.         register mblk_t *omp;
  1944.         /*
  1945.          * Throw away something..
  1946.          */
  1947.         omp = getq(q->q_next);
  1948.         freemsg(omp);
  1949. #endif
  1950. #ifdef    DISCARD_NEWEST
  1951.         freemsg(mp);
  1952.         break;
  1953. #endif
  1954.         }
  1955.         /*
  1956.          * Just send this along..
  1957.          */
  1958.      default:
  1959.         DLOG("ppp_dial_rsrv: M_DATA\n", 0);
  1960.         putnext(q, mp);
  1961.     }
  1962.     }
  1963. }
  1964.  
  1965. static
  1966. duipreq(m0, dst, ifp, checkit)
  1967. struct mbuf *m0;
  1968. struct sockaddr *dst;
  1969. struct ifnet *ifp;
  1970. int checkit;
  1971. {
  1972.     register mblk_t *mp;
  1973.     struct dp_req *req;
  1974.     struct mbuf *m;
  1975.     int s;
  1976.     int i;
  1977.     int len;
  1978.     queue_t *q;
  1979.  
  1980.     /*
  1981.      * If no program is accepting requests, return immediate failure.
  1982.      */
  1983.     if (!(q = req_q))
  1984.     return -1;
  1985.     /*
  1986.      * Check how much header we have and arrange to send at least
  1987.      * DR_MINHDRLEN but not more than DR_MAXHDRLEN to the program
  1988.      * handling calls (dpd).
  1989.      */
  1990.     for (len = 0, m = m0 ; m && len <= DR_MAXHDRLEN ; m = m->m_next)
  1991.     len += m->m_len;
  1992.     if (len < DR_MINHDRLEN)
  1993.     return -1;
  1994.     if (len > DR_MAXHDRLEN)
  1995.     len = DR_MAXHDRLEN;
  1996.  
  1997.     /*
  1998.      * Allocate the appropriate stream data structure for this request.
  1999.      */
  2000.     s = splstr();
  2001.     mp = allocb(sizeof(struct dp_reqinfo) + len, BPRI_MED);
  2002.     if (!mp) {
  2003.     splx(s);
  2004.     return -1;
  2005.     }
  2006.  
  2007.     /*
  2008.      * Fill in the request info.
  2009.      */
  2010.     req = (struct dp_req *)mp->b_wptr;
  2011.     mp->b_wptr += sizeof (struct dp_reqinfo);
  2012.     for (i = 0 ; i < sizeof(req->dr_ifname) ; i++)
  2013.     if (!(req->dr_ifname[i] = ifp->if_name[i]))
  2014.         break;
  2015.     for ( i++ ; i < sizeof(req->dr_ifname) ; i++)
  2016.     req->dr_ifname[i] = '\0';
  2017.     req->dr_ifunit = ifp->if_unit;
  2018.     req->dr_flag = checkit ? DP_REQ_CHECKIT : 0;
  2019.     bcopy(dst, &req->dr_sin, sizeof(struct sockaddr_in));
  2020.     req->dr_hdrlen = len;
  2021.     /*
  2022.      * Copy the header data, in chunks if necessary.
  2023.      */
  2024.     for (m = m0 ; len > 0 && m ; m = m->m_next) {
  2025.     i = MIN(len, m->m_len);
  2026.     bcopy(mtod(m, char *), mp->b_wptr, i);
  2027.     len -= i;
  2028.     mp->b_wptr += i;
  2029.     }
  2030.     /*
  2031.      * Send this stream stuff to the program.
  2032.      */
  2033.     putq(q, mp);
  2034.     splx(s);
  2035.     DLOG("duipreq\n", 0);
  2036.     return 0;
  2037. }
  2038.  
  2039. /*
  2040.  * slcompress.c is included here with small changes, to make loadable
  2041.  * module implementation easier... peter@@micromuse.co.uk
  2042.  */
  2043.  
  2044. /*
  2045.  * Routines to compress and uncompess tcp packets (for transmission
  2046.  * over low speed serial lines.
  2047.  *
  2048.  * Copyright (c) 1989 Regents of the University of California.
  2049.  * All rights reserved.
  2050.  *
  2051.  * Redistribution and use in source and binary forms are permitted
  2052.  * provided that the above copyright notice and this paragraph are
  2053.  * duplicated in all such forms and that any documentation,
  2054.  * advertising materials, and other materials related to such
  2055.  * distribution and use acknowledge that the software was developed
  2056.  * by the University of California, Berkeley.  The name of the
  2057.  * University may not be used to endorse or promote products derived
  2058.  * from this software without specific prior written permission.
  2059.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  2060.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  2061.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  2062.  *
  2063.  *    Van Jacobson (van@@helios.ee.lbl.gov), Dec 31, 1989:
  2064.  *    - Initial distribution.
  2065.  */
  2066.  
  2067. #ifndef SL_NO_STATS
  2068. #define SLINCR(counter) ++comp->counter;
  2069. #else
  2070. #define SLINCR(counter)
  2071. #endif
  2072.  
  2073. #define SLBCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
  2074. #define SLBCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
  2075. #ifndef KERNEL
  2076. #define ovbcopy bcopy
  2077. #endif
  2078.  
  2079.  
  2080. static void
  2081. sl_compress_init(comp)
  2082.     struct slcompress *comp;
  2083. {
  2084.     register u_int i;
  2085.     register struct cstate *tstate = comp->tstate;
  2086.  
  2087.     bzero((char *)comp, sizeof(*comp));
  2088.     for (i = MAX_STATES - 1; i > 0; --i) {
  2089.         tstate[i].cs_id = i;
  2090.         tstate[i].cs_next = &tstate[i - 1];
  2091.     }
  2092.     tstate[0].cs_next = &tstate[MAX_STATES - 1];
  2093.     tstate[0].cs_id = 0;
  2094.     comp->last_cs = &tstate[0];
  2095.     comp->last_recv = 255;
  2096.     comp->last_xmit = 255;
  2097.     comp->flags = SLF_TOSS;
  2098. }
  2099.  
  2100.  
  2101. /* ENCODE encodes a number that is known to be non-zero.  ENCODEZ
  2102.  * checks for zero (since zero has to be encoded in the long, 3 byte
  2103.  * form).
  2104.  */
  2105. #define ENCODE(n) { \
  2106.     if ((u_short)(n) >= 256) { \
  2107.         *cp++ = 0; \
  2108.         cp[1] = (n); \
  2109.         cp[0] = (n) >> 8; \
  2110.         cp += 2; \
  2111.     } else { \
  2112.         *cp++ = (n); \
  2113.     } \
  2114. }
  2115. #define ENCODEZ(n) { \
  2116.     if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
  2117.         *cp++ = 0; \
  2118.         cp[1] = (n); \
  2119.         cp[0] = (n) >> 8; \
  2120.         cp += 2; \
  2121.     } else { \
  2122.         *cp++ = (n); \
  2123.     } \
  2124. }
  2125.  
  2126. #define DECODEL(f) { \
  2127.     if (*cp == 0) {\
  2128.         (f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
  2129.         cp += 3; \
  2130.     } else { \
  2131.         (f) = htonl(ntohl(f) + (u_long)*cp++); \
  2132.     } \
  2133. }
  2134.  
  2135. #define DECODES(f) { \
  2136.     if (*cp == 0) {\
  2137.         (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
  2138.         cp += 3; \
  2139.     } else { \
  2140.         (f) = htons(ntohs(f) + (u_long)*cp++); \
  2141.     } \
  2142. }
  2143.  
  2144. #define DECODEU(f) { \
  2145.     if (*cp == 0) {\
  2146.         (f) = htons((cp[1] << 8) | cp[2]); \
  2147.         cp += 3; \
  2148.     } else { \
  2149.         (f) = htons((u_long)*cp++); \
  2150.     } \
  2151. }
  2152.  
  2153.  
  2154. static u_char
  2155. sl_compress_tcp(m, ip, comp, compress_cid)
  2156.     struct mbuf *m;
  2157.     register struct ip *ip;
  2158.     struct slcompress *comp;
  2159.     int compress_cid;
  2160. {
  2161.     register struct cstate *cs = comp->last_cs->cs_next;
  2162.     register u_int hlen = ip->ip_hl;
  2163.     register struct tcphdr *oth;
  2164.     register struct tcphdr *th;
  2165.     register u_int deltaS, deltaA;
  2166.     register u_int changes = 0;
  2167.     u_char new_seq[16];
  2168.     register u_char *cp = new_seq;
  2169.  
  2170.     /*
  2171.      * Bail if this is an IP fragment or if the TCP packet isn't
  2172.      * `compressible' (i.e., ACK isn't set or some other control bit is
  2173.      * set).  (We assume that the caller has already made sure the
  2174.      * packet is IP proto TCP).
  2175.      */
  2176.     if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40)
  2177.         return (TYPE_IP);
  2178.  
  2179.     th = (struct tcphdr *)&((int *)ip)[hlen];
  2180.     if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
  2181.         return (TYPE_IP);
  2182.     /*
  2183.      * Packet is compressible -- we're going to send either a
  2184.      * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
  2185.      * to locate (or create) the connection state.  Special case the
  2186.      * most recently used connection since it's most likely to be used
  2187.      * again & we don't have to do any reordering if it's used.
  2188.      */
  2189.     SLINCR(sls_packets)
  2190.     if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
  2191.         ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
  2192.         *(int *)th != ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl]) {
  2193.         /*
  2194.          * Wasn't the first -- search for it.
  2195.          *
  2196.          * States are kept in a circularly linked list with
  2197.          * last_cs pointing to the end of the list.  The
  2198.          * list is kept in lru order by moving a state to the
  2199.          * head of the list whenever it is referenced.  Since
  2200.          * the list is short and, empirically, the connection
  2201.          * we want is almost always near the front, we locate
  2202.          * states via linear search.  If we don't find a state
  2203.          * for the datagram, the oldest state is (re-)used.
  2204.          */
  2205.         register struct cstate *lcs;
  2206.         register struct cstate *lastcs = comp->last_cs;
  2207.  
  2208.         do {
  2209.             lcs = cs; cs = cs->cs_next;
  2210.             SLINCR(sls_searches)
  2211.             if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
  2212.                 && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
  2213.                 && *(int *)th == ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl])
  2214.                 goto found;
  2215.         } while (cs != lastcs);
  2216.  
  2217.         /*
  2218.          * Didn't find it -- re-use oldest cstate.  Send an
  2219.          * uncompressed packet that tells the other side what
  2220.          * connection number we're using for this conversation.
  2221.          * Note that since the state list is circular, the oldest
  2222.          * state points to the newest and we only need to set
  2223.          * last_cs to update the lru linkage.
  2224.          */
  2225.         SLINCR(sls_misses)
  2226.         comp->last_cs = lcs;
  2227.         hlen += th->th_off;
  2228.         hlen <<= 2;
  2229.         goto uncompressed;
  2230.  
  2231.     found:
  2232.         /*
  2233.          * Found it -- move to the front on the connection list.
  2234.          */
  2235.         if (cs == lastcs)
  2236.             comp->last_cs = lcs;
  2237.         else {
  2238.             lcs->cs_next = cs->cs_next;
  2239.             cs->cs_next = lastcs->cs_next;
  2240.             lastcs->cs_next = cs;
  2241.         }
  2242.     }
  2243.  
  2244.     /*
  2245.      * Make sure that only what we expect to change changed. The first
  2246.      * line of the `if' checks the IP protocol version, header length &
  2247.      * type of service.  The 2nd line checks the "Don't fragment" bit.
  2248.      * The 3rd line checks the time-to-live and protocol (the protocol
  2249.      * check is unnecessary but costless).  The 4th line checks the TCP
  2250.      * header length.  The 5th line checks IP options, if any.  The 6th
  2251.      * line checks TCP options, if any.  If any of these things are
  2252.      * different between the previous & current datagram, we send the
  2253.      * current datagram `uncompressed'.
  2254.      */
  2255.     oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];
  2256.     deltaS = hlen;
  2257.     hlen += th->th_off;
  2258.     hlen <<= 2;
  2259.  
  2260.     if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||
  2261.         ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||
  2262.         ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||
  2263.         th->th_off != oth->th_off ||
  2264.         (deltaS > 5 &&
  2265.          SLBCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
  2266.         (th->th_off > 5 &&
  2267.          SLBCMP(th + 1, oth + 1, (th->th_off - 5) << 2)))
  2268.         goto uncompressed;
  2269.  
  2270.     /*
  2271.      * Figure out which of the changing fields changed.  The
  2272.      * receiver expects changes in the order: urgent, window,
  2273.      * ack, seq (the order minimizes the number of temporaries
  2274.      * needed in this section of code).
  2275.      */
  2276.     if (th->th_flags & TH_URG) {
  2277.         deltaS = ntohs(th->th_urp);
  2278.         ENCODEZ(deltaS);
  2279.         changes |= NEW_U;
  2280.     } else if (th->th_urp != oth->th_urp)
  2281.         /* argh! URG not set but urp changed -- a sensible
  2282.          * implementation should never do this but RFC793
  2283.          * doesn't prohibit the change so we have to deal
  2284.          * with it. */
  2285.          goto uncompressed;
  2286.  
  2287.     if (deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) {
  2288.         ENCODE(deltaS);
  2289.         changes |= NEW_W;
  2290.     }
  2291.  
  2292.     if (deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack)) {
  2293.         if (deltaA > 0xffff)
  2294.             goto uncompressed;
  2295.         ENCODE(deltaA);
  2296.         changes |= NEW_A;
  2297.     }
  2298.  
  2299.     if (deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq)) {
  2300.         if (deltaS > 0xffff)
  2301.             goto uncompressed;
  2302.         ENCODE(deltaS);
  2303.         changes |= NEW_S;
  2304.     }
  2305.  
  2306.     switch(changes) {
  2307.  
  2308.     case 0:
  2309.         /*
  2310.          * Nothing changed. If this packet contains data and the
  2311.          * last one didn't, this is probably a data packet following
  2312.          * an ack (normal on an interactive connection) and we send
  2313.          * it compressed.  Otherwise it's probably a retransmit,
  2314.          * retransmitted ack or window probe.  Send it uncompressed
  2315.          * in case the other side missed the compressed version.
  2316.          */
  2317.         if (ip->ip_len != cs->cs_ip.ip_len &&
  2318.             ntohs(cs->cs_ip.ip_len) == hlen)
  2319.             break;
  2320.  
  2321.         /* (fall through) */
  2322.  
  2323.     case SPECIAL_I:
  2324.     case SPECIAL_D:
  2325.         /*
  2326.          * actual changes match one of our special case encodings --
  2327.          * send packet uncompressed.
  2328.          */
  2329.         goto uncompressed;
  2330.  
  2331.     case NEW_S|NEW_A:
  2332.         if (deltaS == deltaA &&
  2333.             deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
  2334.             /* special case for echoed terminal traffic */
  2335.             changes = SPECIAL_I;
  2336.             cp = new_seq;
  2337.         }
  2338.         break;
  2339.  
  2340.     case NEW_S:
  2341.         if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
  2342.             /* special case for data xfer */
  2343.             changes = SPECIAL_D;
  2344.             cp = new_seq;
  2345.         }
  2346.         break;
  2347.     }
  2348.  
  2349.     deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
  2350.     if (deltaS != 1) {
  2351.         ENCODEZ(deltaS);
  2352.         changes |= NEW_I;
  2353.     }
  2354.     if (th->th_flags & TH_PUSH)
  2355.         changes |= TCP_PUSH_BIT;
  2356.     /*
  2357.      * Grab the cksum before we overwrite it below.  Then update our
  2358.      * state with this packet's header.
  2359.      */
  2360.     deltaA = ntohs(th->th_sum);
  2361.     SLBCOPY(ip, &cs->cs_ip, hlen);
  2362.  
  2363.     /*
  2364.      * We want to use the original packet as our compressed packet.
  2365.      * (cp - new_seq) is the number of bytes we need for compressed
  2366.      * sequence numbers.  In addition we need one byte for the change
  2367.      * mask, one for the connection id and two for the tcp checksum.
  2368.      * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
  2369.      * many bytes of the original packet to toss so subtract the two to
  2370.      * get the new packet size.
  2371.      */
  2372.     deltaS = cp - new_seq;
  2373.     cp = (u_char *)ip;
  2374.     if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
  2375.         comp->last_xmit = cs->cs_id;
  2376.         hlen -= deltaS + 4;
  2377.         cp += hlen;
  2378.         *cp++ = changes | NEW_C;
  2379.         *cp++ = cs->cs_id;
  2380.     } else {
  2381.         hlen -= deltaS + 3;
  2382.         cp += hlen;
  2383.         *cp++ = changes;
  2384.     }
  2385.     m->m_len -= hlen;
  2386.     m->m_off += hlen;
  2387.     *cp++ = deltaA >> 8;
  2388.     *cp++ = deltaA;
  2389.     SLBCOPY(new_seq, cp, deltaS);
  2390.     SLINCR(sls_compressed)
  2391.     return (TYPE_COMPRESSED_TCP);
  2392.  
  2393.     /*
  2394.      * Update connection state cs & send uncompressed packet ('uncompressed'
  2395.      * means a regular ip/tcp packet but with the 'conversation id' we hope
  2396.      * to use on future compressed packets in the protocol field).
  2397.      */
  2398. uncompressed:
  2399.     SLBCOPY(ip, &cs->cs_ip, hlen);
  2400.     ip->ip_p = cs->cs_id;
  2401.     comp->last_xmit = cs->cs_id;
  2402.     return (TYPE_UNCOMPRESSED_TCP);
  2403. }
  2404.  
  2405.  
  2406. static int
  2407. sl_uncompress_tcp(bufp, len, type, comp)
  2408.     u_char **bufp;
  2409.     int len;
  2410.     u_int type;
  2411.     struct slcompress *comp;
  2412. {
  2413.     register u_char *cp;
  2414.     register u_int hlen, changes;
  2415.     register struct tcphdr *th;
  2416.     register struct cstate *cs;
  2417.     register struct ip *ip;
  2418.  
  2419.     switch (type) {
  2420.  
  2421.     case TYPE_UNCOMPRESSED_TCP:
  2422.         ip = (struct ip *) *bufp;
  2423.         if (ip->ip_p >= MAX_STATES)
  2424.             goto bad;
  2425.         cs = &comp->rstate[comp->last_recv = ip->ip_p];
  2426.         comp->flags &=~ SLF_TOSS;
  2427.         ip->ip_p = IPPROTO_TCP;
  2428.         hlen = ip->ip_hl;
  2429.         hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
  2430.         hlen <<= 2;
  2431.         SLBCOPY(ip, &cs->cs_ip, hlen);
  2432.         cs->cs_ip.ip_sum = 0;
  2433.         cs->cs_hlen = hlen;
  2434.         SLINCR(sls_uncompressedin)
  2435.         return (len);
  2436.  
  2437.     default:
  2438.         goto bad;
  2439.  
  2440.     case TYPE_COMPRESSED_TCP:
  2441.         break;
  2442.     }
  2443.     /* We've got a compressed packet. */
  2444.     SLINCR(sls_compressedin)
  2445.     cp = *bufp;
  2446.     changes = *cp++;
  2447.     if (changes & NEW_C) {
  2448.         /* Make sure the state index is in range, then grab the state.
  2449.          * If we have a good state index, clear the 'discard' flag. */
  2450.         if (*cp >= MAX_STATES)
  2451.             goto bad;
  2452.  
  2453.         comp->flags &=~ SLF_TOSS;
  2454.         comp->last_recv = *cp++;
  2455.     } else {
  2456.         /* this packet has an implicit state index.  If we've
  2457.          * had a line error since the last time we got an
  2458.          * explicit state index, we have to toss the packet. */
  2459.         if (comp->flags & SLF_TOSS) {
  2460.             SLINCR(sls_tossed)
  2461.             return (0);
  2462.         }
  2463.     }
  2464.     cs = &comp->rstate[comp->last_recv];
  2465.     hlen = cs->cs_ip.ip_hl << 2;
  2466.     th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
  2467.     th->th_sum = htons((*cp << 8) | cp[1]);
  2468.     cp += 2;
  2469.     if (changes & TCP_PUSH_BIT)
  2470.         th->th_flags |= TH_PUSH;
  2471.     else
  2472.         th->th_flags &=~ TH_PUSH;
  2473.  
  2474.     switch (changes & SPECIALS_MASK) {
  2475.     case SPECIAL_I:
  2476.         {
  2477.         register u_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
  2478.         th->th_ack = htonl(ntohl(th->th_ack) + i);
  2479.         th->th_seq = htonl(ntohl(th->th_seq) + i);
  2480.         }
  2481.         break;
  2482.  
  2483.     case SPECIAL_D:
  2484.         th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
  2485.                    - cs->cs_hlen);
  2486.         break;
  2487.  
  2488.     default:
  2489.         if (changes & NEW_U) {
  2490.             th->th_flags |= TH_URG;
  2491.             DECODEU(th->th_urp)
  2492.         } else
  2493.             th->th_flags &=~ TH_URG;
  2494.         if (changes & NEW_W)
  2495.             DECODES(th->th_win)
  2496.         if (changes & NEW_A)
  2497.             DECODEL(th->th_ack)
  2498.         if (changes & NEW_S)
  2499.             DECODEL(th->th_seq)
  2500.         break;
  2501.     }
  2502.     if (changes & NEW_I) {
  2503.         DECODES(cs->cs_ip.ip_id)
  2504.     } else
  2505.         cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
  2506.  
  2507.     /*
  2508.      * At this point, cp points to the first byte of data in the
  2509.      * packet.  If we're not aligned on a 4-byte boundary, copy the
  2510.      * data down so the ip & tcp headers will be aligned.  Then back up
  2511.      * cp by the tcp/ip header length to make room for the reconstructed
  2512.      * header (we assume the packet we were handed has enough space to
  2513.      * prepend 128 bytes of header).  Adjust the length to account for
  2514.      * the new header & fill in the IP total length.
  2515.      */
  2516.     len -= (cp - *bufp);
  2517.     if (len < 0)
  2518.         /* we must have dropped some characters (crc should detect
  2519.          * this but the old slip framing won't) */
  2520.         goto bad;
  2521.  
  2522.     if ((int)cp & 3) {
  2523.         if (len > 0)
  2524.             (void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), len);
  2525.         cp = (u_char *)((int)cp &~ 3);
  2526.     }
  2527.     cp -= cs->cs_hlen;
  2528.     len += cs->cs_hlen;
  2529.     cs->cs_ip.ip_len = htons(len);
  2530.     SLBCOPY(&cs->cs_ip, cp, cs->cs_hlen);
  2531.     *bufp = cp;
  2532.  
  2533.     /* recompute the ip header checksum */
  2534.     {
  2535.         register u_short *bp = (u_short *)cp;
  2536.         for (changes = 0; hlen > 0; hlen -= 2)
  2537.             changes += *bp++;
  2538.         changes = (changes & 0xffff) + (changes >> 16);
  2539.         changes = (changes & 0xffff) + (changes >> 16);
  2540.         ((struct ip *)cp)->ip_sum = ~ changes;
  2541.     }
  2542.     return (len);
  2543. bad:
  2544.     comp->flags |= SLF_TOSS;
  2545.     SLINCR(sls_errorin)
  2546.     return (0);
  2547. }
  2548.  
  2549. #ifdef    LOADABLE
  2550.  
  2551. #define    LOG_INUSE    1
  2552.  
  2553. struct cdevsw ppp_cdevsw = {
  2554.      0, 0, 0, 0, 0, 0, 0, 0, &ppp_dialinfo, 0
  2555. };
  2556.  
  2557. static struct log { 
  2558.     char flags;
  2559.     char nr;
  2560. } dp_if_log[NDP], ppp_dial_log[NDP];
  2561.  
  2562. static struct vdldrv ppp_dial_vd = {
  2563.     VDMAGIC_PSEUDO,
  2564.     "Dialup PPP Interface",
  2565. #if    defined(sun4c) || defined(sun4m)
  2566.     NULL,
  2567. #else
  2568.     (struct mb_ctlr *)NULL,
  2569.     (struct mb_driver *)NULL,
  2570.     (struct mb_device *)NULL,
  2571.     NULL,
  2572.     NULL,
  2573. #endif
  2574.     NULL,
  2575.     &ppp_cdevsw,
  2576.     0,
  2577.     0,
  2578. };
  2579.  
  2580. static struct fmodsw *fmod_dp_if;
  2581. static struct fmodsw *fmod_ppp_dial;
  2582.  
  2583. dpmod_init(fc,vdp,vdi,vds)
  2584. unsigned int fc;
  2585. struct vddrv *vdp;
  2586. addr_t vdi;
  2587. struct vdstat *vds;
  2588. {
  2589.     dp_if_init(fc, vdp, vdi, vds);
  2590.     ppp_dial_init(fc, vdp, vdi, vds);
  2591.     return 0;
  2592. }
  2593.  
  2594.  
  2595. static
  2596. dp_if_init(fc,vdp,vdi,vds)
  2597. unsigned int fc;
  2598. struct vddrv *vdp;
  2599. addr_t vdi;
  2600. struct vdstat *vds;
  2601. {
  2602.     register int i;
  2603.     register struct dp_if_info *p;
  2604.     switch(fc) {
  2605.         case VDLOAD:
  2606.         {
  2607.             register int i;
  2608.             for(i = 0; i < fmodcnt; i++) {
  2609.                 if(fmodsw[i].f_str == NULL)
  2610.                     break;
  2611.             }
  2612.             if(i == fmodcnt)
  2613.                 return(ENODEV);
  2614.             fmod_dp_if = &fmodsw[i];
  2615.             fmod_dp_if->f_str = &dp_ifinfo;
  2616.             bcopy(dp_minfo.mi_idname, fmod_dp_if->f_name, FMNAMESZ);
  2617.             for (i = 0; i < NDP; i++)
  2618.                 dp_attach(i);
  2619.         return 0;
  2620.         }
  2621.  
  2622. /* Paul Fox says you only need this line if you have a real device
  2623.  * to add to the cdevsw/bdevsw structures, so this should be safe :-)
  2624.  * (It seems to work) It goes above by the way.
  2625.  *
  2626.  *        vdp->vdd_vdtab = (struct vdlinkage *) &dp_if_vd;
  2627.  */
  2628.         case VDUNLOAD:
  2629.         {
  2630.             int dev;
  2631.             for (dev = 0; dev < NDP; dev++) 
  2632.                 if (dupii[dev].pii_flags & PII_FLAGS_INUSE)
  2633.                     return (EBUSY);
  2634.             }
  2635.             for (i = 0, p = dupii; i < NDP; i++, p++) {
  2636.             /***********************************************/
  2637.             /*   Loadable  driver  needs  to  detach from  */
  2638.             /*   ifnet   structure   otherwise  we  panic  */
  2639.             /*   system  as  soon  as  if_slowtimo() goes  */
  2640.             /*   off  because  it  has a list pointing to  */
  2641.             /*   the   memory   which   will   have  been  */
  2642.             /*   deallocated.                   */
  2643.             /***********************************************/
  2644.             if (p->pii_flags & PII_FLAGS_ATTACHED) {
  2645.                 if (dp_detach(p) == 0)
  2646.                     return EBUSY;
  2647.                 p->pii_flags &= ~PII_FLAGS_ATTACHED;
  2648.                 }
  2649.             fmod_dp_if->f_name[0] = '\0';
  2650.             fmod_dp_if->f_str = NULL;
  2651.         }
  2652.             return 0;
  2653.         case VDSTAT:
  2654.             return 0;
  2655.         default:
  2656.             return EIO;
  2657.     }
  2658. }
  2659.  
  2660. static
  2661. ppp_dial_init(fc,vdp,vdi,vds)
  2662. unsigned int fc;
  2663. struct vddrv *vdp;
  2664. addr_t vdi;
  2665. struct vdstat *vds;
  2666. {
  2667.     register int i;
  2668.     switch(fc) {
  2669.         case VDLOAD:
  2670.         {
  2671.             for(i=0; i < fmodcnt; i++) {
  2672.                 if(fmodsw[i].f_str == NULL)
  2673.                     break;
  2674.             }
  2675.             if(i == fmodcnt)
  2676.                 return(ENODEV);
  2677.             fmod_ppp_dial = &fmodsw[i];
  2678.             fmod_ppp_dial->f_str = &ppp_dialinfo;
  2679.             bcopy(ppp_dial_minfo.mi_idname, fmod_ppp_dial->f_name, FMNAMESZ);
  2680.             vdp->vdd_vdtab = (struct vdlinkage *) &ppp_dial_vd;
  2681.             return 0;
  2682.         }
  2683.         case VDUNLOAD:
  2684.         {
  2685.             for (i = 0; i < NDP; i++) 
  2686.                 if (ppp_dial_log[i].flags & LOG_INUSE)
  2687.                     return (EIO);
  2688.             fmod_ppp_dial->f_name[0] = '\0';
  2689.             fmod_ppp_dial->f_str = NULL;
  2690.             return 0;
  2691.         }
  2692.         case VDSTAT:
  2693.             return 0;
  2694.         default:
  2695.             return EIO;
  2696.     }
  2697. }
  2698.  
  2699. /**********************************************************************/
  2700. /*   Routine  to  detach a PPP device from the ifnet structure (list  */
  2701. /*   of  interfaces).  Kernel doesn't provide any routines for doing  */
  2702. /*   this  for  loadable  device  drivers and we must avoid panicing  */
  2703. /*   the system.                              */
  2704. /**********************************************************************/
  2705. static int
  2706. dp_detach(pp)
  2707. register struct dp_if_info *pp;
  2708. {    struct ifnet **p = &ifnet;
  2709.     struct ifnet *ifp = &pp->pii_ifnet;
  2710.  
  2711.     while (*p) {
  2712.         if (*p == ifp) {
  2713.             *p = ifp->if_next;
  2714.             return 1;
  2715.             }
  2716.         p = &((*p)->if_next);
  2717.         }
  2718.     return 0;
  2719. }
  2720.  
  2721. #endif /* LOADABLE */
  2722. #endif NDP > 0
  2723. @
  2724.  
  2725.  
  2726. 1.34
  2727. log
  2728. @sun4m support
  2729. @
  2730. text
  2731. @d378 1
  2732. a378 1
  2733.         log(LOG_INFO, "dp_callstat: state %s stat %d\n",
  2734. d381 1
  2735. a381 1
  2736.         log(LOG_INFO, "dp_callstat: state %s stat %s\n",
  2737. @
  2738.  
  2739.  
  2740. 1.33
  2741. log
  2742. @Fixed error in loadable module support.
  2743. @
  2744. text
  2745. @d2371 3
  2746. a2373 1
  2747. #ifndef    sun4c
  2748. d2379 1
  2749. a2379 3
  2750. #else    sun4c
  2751.     NULL,
  2752. #endif    sun4c
  2753. @
  2754.  
  2755.  
  2756. 1.32
  2757. log
  2758. @*** empty log message ***
  2759. @
  2760. text
  2761. @d2373 2
  2762. a2374 2
  2763.     (struct mb_driver *)ULL,
  2764.     (struct mb_device *)ULL,
  2765. @
  2766.  
  2767.  
  2768. 1.31
  2769. log
  2770. @Lint things..
  2771. @
  2772. text
  2773. @d80 3
  2774. d84 1
  2775. @
  2776.  
  2777.  
  2778. 1.30
  2779. log
  2780. @Added #ifdef for non-sun4c architectures.
  2781. @
  2782. text
  2783. @d2368 3
  2784. a2370 3
  2785.     NULL,
  2786.     NULL,
  2787.     NULL,
  2788. @
  2789.  
  2790.  
  2791. 1.29
  2792. log
  2793. @Corrected module name in module definition..
  2794. @
  2795. text
  2796. @d2367 1
  2797. d2369 7
  2798. @
  2799.  
  2800.  
  2801. 1.28
  2802. log
  2803. @Make includes a little different for LOADABLE version.
  2804. @
  2805. text
  2806. @d29 1
  2807. a29 1
  2808.  * "dp_if" streams module
  2809. d36 1
  2810. a36 1
  2811.  *    the "dp_if" streams module for input and output on the serial
  2812. d39 1
  2813. a39 1
  2814.  * "ppp_dial" streams device
  2815. d160 1
  2816. a160 1
  2817.     0xbad,"dp_if",0, INFPSZ, 16384, 4096
  2818. d1636 1
  2819. a1636 1
  2820.     0xbae,"ppp_dial",0, INFPSZ, DP_HIWAT, DP_LOWAT
  2821. @
  2822.  
  2823.  
  2824. 1.27
  2825. log
  2826. @Bug fix..
  2827. @
  2828. text
  2829. @d87 3
  2830. d92 5
  2831. d99 1
  2832. @
  2833.  
  2834.  
  2835. 1.26
  2836. log
  2837. @Peter Galbavy's updates.
  2838. It now almost handles loadable drivers.
  2839. It does NIT stuff.
  2840. The slcompress module was moved into this file so that it could by
  2841. dynamically loaded.
  2842.  
  2843. @
  2844. text
  2845. @d1890 1
  2846. @
  2847.  
  2848.  
  2849. 1.25
  2850. log
  2851. @Bug fix from Peter Galbavy and Paul Fox for error accounting.
  2852. @
  2853. text
  2854. @a0 4
  2855. /* dp_if.c - Streams PPP top level module handles if_ and packetizing PPP packets.
  2856.     Copyright (C) 1990  Brad K. Clements, All Rights Reserved
  2857.     See copyright notice in Readme.streams
  2858. */
  2859. d2 5
  2860. d48 1
  2861. d50 1
  2862. d52 1
  2863. d56 1
  2864. d87 1
  2865. a87 1
  2866. #include "slcompress.h"
  2867. d94 1
  2868. a94 1
  2869. char *dus_str[] = {
  2870. d103 1
  2871. a103 1
  2872. char *cstat_str[] = {
  2873. d130 16
  2874. d168 2
  2875. a169 2
  2876. int    dp_output(), dp_ioctl();
  2877. static int dp_start(), dp_timer(), dp_flush();
  2878. d185 1
  2879. a185 1
  2880. int
  2881. d193 1
  2882. a193 1
  2883.     ifp->if_mtu  = PPP_MTU;
  2884. d195 2
  2885. a196 2
  2886.     ifp->if_unit  = unit;
  2887.     ifp->if_ioctl  = dp_ioctl;
  2888. d205 1
  2889. d245 1
  2890. d317 1
  2891. a317 1
  2892. static
  2893. d791 14
  2894. d907 11
  2895. d1159 1
  2896. d1180 1
  2897. d1215 1
  2898. d1229 1
  2899. d1247 1
  2900. d1758 1
  2901. d1831 675
  2902. @
  2903.  
  2904.  
  2905. 1.24
  2906. log
  2907. @Merged in ppp_dial.c stuff..
  2908. @
  2909. text
  2910. @d593 1
  2911. a593 1
  2912.     switch (c) {
  2913. @
  2914.  
  2915.  
  2916. 1.23
  2917. log
  2918. @Added statistics gathering stuff.
  2919. @
  2920. text
  2921. @d24 20
  2922. d129 1
  2923. a129 1
  2924. static     struct    module_info    minfo ={
  2925. d133 2
  2926. a134 2
  2927. static    struct    qinit    r_init = {
  2928.     dp_if_rput, dp_if_rsrv, dp_if_open, dp_if_close, NULL, &minfo, NULL
  2929. d136 2
  2930. a137 2
  2931. static    struct    qinit    w_init = {
  2932.     dp_if_wput, dp_if_wsrv, dp_if_open, dp_if_close, NULL, &minfo, NULL
  2933. d140 1
  2934. a140 1
  2935.     &r_init, &w_init, NULL, NULL, NULL
  2936. d1552 224
  2937. @
  2938.  
  2939.  
  2940. 1.22
  2941. log
  2942. @Fixed handling of multiple PPP's trying to attach to the same network
  2943. interface.
  2944. @
  2945. text
  2946. @d1075 8
  2947. d1089 20
  2948. @
  2949.  
  2950.  
  2951. 1.21
  2952. log
  2953. @Clean up state transitions for dial-in/dial-out multiple modem case.
  2954. Add NO_MODEM status.
  2955. @
  2956. text
  2957. @d210 6
  2958. d219 4
  2959. a222 1
  2960.     DLOG("dp_if_unit: enter %d\n", unit);
  2961. d237 1
  2962. d453 2
  2963. a454 7
  2964.         x = *(int *)mp->b_cont->b_rptr;
  2965.         if (x < 0 || x > NDP || q->q_ptr) {
  2966.         /*
  2967.          * Can only set the unit once,
  2968.          * and it better be within the proper range.
  2969.          */
  2970.         i->ioc_error = ENXIO;
  2971. d457 4
  2972. a460 5
  2973.         DLOG2("before dp_if_unit %x %x\n", q, mp);
  2974.         dp_if_unit(q, x);
  2975.         DLOG2("after  dp_if_unit %x %x\n", q, mp);
  2976.         p = (PII *) q->q_ptr;
  2977.         goto iocack;
  2978. @
  2979.  
  2980.  
  2981. 1.20
  2982. log
  2983. @Handle RSTs in addition to FINs for the fast timeout mechanism.
  2984. @
  2985. text
  2986. @d78 6
  2987. d292 12
  2988. d307 1
  2989. a307 1
  2990. int stat;
  2991. d309 23
  2992. a331 9
  2993.     switch (stat) {
  2994.      case DP_SUCCESS:
  2995.     /*
  2996.      * Call succeeded
  2997.      */
  2998.     DLOGFLAGS("dp_callstat: call succeeded %x %x\n");
  2999.     switch (p->pii_dustate) {
  3000.      case PII_DPS_ACTIVE:
  3001.      case PII_DPS_DOWN:
  3002. d333 1
  3003. a333 1
  3004.      default:
  3005. a334 1
  3006.         (void)dp_start(p);
  3007. d337 10
  3008. a346 9
  3009.     break;
  3010.      case DP_FAILURE:
  3011.     /*
  3012.      * Call failed
  3013.      */
  3014.     DLOGFLAGS("dp_callstat: call failed %x %x\n");
  3015.     switch (p->pii_dustate) {
  3016.      case PII_DPS_FAILCALL:
  3017.      case PII_DPS_DOWN:
  3018. d348 1
  3019. a348 1
  3020.      default:
  3021. d352 3
  3022. a356 13
  3023.      case DP_IN_PROGRESS:
  3024.     /*
  3025.      * Call in progress (PPP negotiation happening)
  3026.      */
  3027.     DLOGFLAGS("dp_callstat: call in progress %x %x\n");
  3028.     switch (p->pii_dustate) {
  3029.      case PII_DPS_DISCON:
  3030.      case PII_DPS_WAITING:
  3031.      case PII_DPS_FAILCALL:
  3032.         dp_state(p, PII_DPS_WAITING);
  3033.         break;
  3034.     }
  3035.     break;
  3036. a524 1
  3037.  
  3038. d1171 6
  3039. a1176 1
  3040.  *  Watchdog timer.
  3041. @
  3042.  
  3043.  
  3044. 1.19
  3045. log
  3046. @Added copyright
  3047. @
  3048. text
  3049. @d1270 2
  3050. d1314 1
  3051. a1314 1
  3052.     if (len < hlen + sizeof(int)) {
  3053. d1419 1
  3054. a1419 1
  3055.     if (th->th_flags & TH_FIN) {
  3056. d1425 1
  3057. a1425 1
  3058.         DLOG_ACTIVE("FIN");
  3059. d1438 36
  3060. @
  3061.  
  3062.  
  3063. 1.18
  3064. log
  3065. @Fixed the no timeout case.
  3066. @
  3067. text
  3068. @d5 19
  3069. @
  3070.  
  3071.  
  3072. 1.17
  3073. log
  3074. @Fixed major bug with debugging statements.
  3075. @
  3076. text
  3077. @d106 7
  3078. a112 7
  3079.     DP_DEF_ATIMEO / DP_HZ,        /* Activity Timeout */
  3080.     DP_DEF_CTIMEO / DP_HZ,        /* Last TCP Close Timeout */
  3081.     DP_DEF_UTIMEO / DP_HZ,        /* Non-TCP traffic timeout */
  3082.     DP_DEF_WTIMEO / DP_HZ,        /* Call Wait Timeout */
  3083.     DP_DEF_FTIMEO / DP_HZ,        /* Failed Call Timeout */
  3084.     DP_NO_TIMEOUT,            /* No Disconnect Timeout */
  3085.     DP_NO_TIMEOUT            /* No Down Timeout */
  3086. d1046 7
  3087. a1052 1
  3088.     if (to[t] != DP_DEF_TIMEOUT)
  3089. d1054 2
  3090. @
  3091.  
  3092.  
  3093. 1.16
  3094. log
  3095. @Don't consider inactive conversations when looking for LRU slots in
  3096. the routine that keeps track of active connections.
  3097. @
  3098. text
  3099. @d606 1
  3100. a606 1
  3101.             DLOG("dp: sl_uncompress failed on type Compressed",0);;
  3102. d1260 3
  3103. d1295 1
  3104. d1297 1
  3105. @
  3106.  
  3107.  
  3108. 1.15
  3109. log
  3110. @Changed the timeout mechanism to employ a fast timer for fast disconnects.
  3111. @
  3112. text
  3113. @d1307 1
  3114. d1329 1
  3115. d1331 6
  3116. a1336 2
  3117.      * This conversation is not in our table.
  3118.      * Create an entry for it in the least recently used slot.
  3119. d1338 22
  3120. a1359 1
  3121.     tab->dt_last = lconv;
  3122. d1371 2
  3123. a1372 1
  3124.      * New conversation.
  3125. d1374 1
  3126. @
  3127.  
  3128.  
  3129. 1.14
  3130. log
  3131. @Set/get interface timeouts changed since we now have too many for one
  3132. ioctl.
  3133. @
  3134. text
  3135. @a46 1
  3136. #ifdef    DP_ACTIVE
  3137. a47 1
  3138. #endif
  3139. d66 1
  3140. d68 2
  3141. d77 1
  3142. a114 1
  3143. #ifdef    DP_ACTIVE
  3144. a117 1
  3145. #endif    DP_ACTIVE
  3146. a194 1
  3147. #ifdef    DP_ACTIVE
  3148. a195 1
  3149. #endif    DP_ACTIVE
  3150. a705 1
  3151. #ifdef    DP_ACTIVE
  3152. d707 1
  3153. a707 1
  3154.     dp_active(&p->pii_active, (struct ip *)(mtod(mb1, u_char *) + IPADJ),
  3155. a708 1
  3156. #endif    DP_ACTIVE
  3157. d892 1
  3158. a892 3
  3159. #ifdef    DP_ACTIVE
  3160.         dp_active(&p->pii_active, ip, m0->m_len, 1);
  3161. #endif    DP_ACTIVE
  3162. d1015 1
  3163. a1015 1
  3164.             DP_ATIMEO, DP_NATIMEOUTS);
  3165. d1019 1
  3166. a1019 1
  3167.             DP_ATIMEO, DP_NATIMEOUTS);
  3168. d1024 1
  3169. a1024 1
  3170.             DP_WTIMEO, DP_NCTIMEOUTS);
  3171. d1028 1
  3172. a1028 1
  3173.             DP_WTIMEO, DP_NCTIMEOUTS);
  3174. d1045 1
  3175. a1045 1
  3176.     for (t = t0 + nt -1 ; t >= t0 ; t--)
  3177. d1047 1
  3178. a1047 1
  3179.         p->pii_timo[t] = to[t] / DP_HZ;
  3180. d1053 2
  3181. a1054 2
  3182.     p->pii_timo[DP_CTIMEO] == DP_NO_TIMEOUT)
  3183.     p->pii_active.da_flags &= ~DA_INUSE;
  3184. d1056 1
  3185. a1056 1
  3186.     p->pii_active.da_flags |=  DA_INUSE;
  3187. d1058 2
  3188. d1065 1
  3189. a1065 1
  3190. dp_gettimos(p, to)
  3191. d1068 1
  3192. d1071 2
  3193. a1072 2
  3194.     for (t = 0 ; t < DP_NTIMEOUTS ; t++)
  3195.     to[t] = p->pii_timo[t] * DP_HZ;
  3196. d1087 6
  3197. a1092 1
  3198.     p->pii_ifnet.if_timer = (p->pii_timer || p->pii_ftimer) ? DP_HZ : 0;
  3199. d1102 5
  3200. d1111 1
  3201. d1113 7
  3202. a1119 1
  3203.     p->pii_ifnet.if_timer = (p->pii_timer || p->pii_ftimer) ? DP_HZ : 0;
  3204. a1132 1
  3205.     DLOGSTATE("dp_timer: before %s\n");
  3206. d1145 5
  3207. d1155 5
  3208. d1173 5
  3209. a1177 1
  3210.     DLOG("dp_timer: %stimer expired\n", p->pii_ftimer == 0 ? "fast " : "");
  3211. a1220 9
  3212. #ifdef    DP_ACTIVE
  3213. #define    DP_ACTIVE_DEBUG
  3214. #ifdef    DP_ACTIVE_DEBUG
  3215. #define    DEBUG_ACTIVE(event)    if (active_debug) log(LOG_INFO, "%c %s %d %d/%d", xmit ? 'T' : 'R', (event), act->da_nactive, act->da_misses, act->da_lookups)
  3216. int active_debug = 0;
  3217. #else
  3218. #define    DEBUG_ACTIVE(event)
  3219. #endif    DP_ACTIVE_DEBUG
  3220.  
  3221. d1250 1
  3222. a1250 1
  3223.     register struct dp_active *act = &p->pii_active;
  3224. d1256 1
  3225. a1256 1
  3226.     if (!(act->da_flags & DA_INUSE)) {
  3227. d1264 1
  3228. a1264 1
  3229.     DEBUG_ACTIVE("len");
  3230. d1272 1
  3231. a1272 1
  3232.     DEBUG_ACTIVE("nontcp");
  3233. d1283 1
  3234. a1283 1
  3235.     DEBUG_ACTIVE("len2");
  3236. d1292 1
  3237. d1351 1
  3238. a1351 1
  3239.     DEBUG_ACTIVE("NEW");
  3240. d1362 1
  3241. a1362 1
  3242.         DEBUG_ACTIVE("FIN");
  3243. d1372 1
  3244. a1372 1
  3245.         DEBUG_ACTIVE("SYN");
  3246. a1375 1
  3247. #endif DP_ACTIVE
  3248. @
  3249.  
  3250.  
  3251. 1.13
  3252. log
  3253. @Updates for new fast timeout mechanism.
  3254. @
  3255. text
  3256. @d458 1
  3257. a458 1
  3258.         dp_settimos(p, (u_long *)mp->b_cont->b_rptr);
  3259. d462 1
  3260. a462 1
  3261.         dp_gettimos(p, (u_long *)mp->b_cont->b_wptr);
  3262. d1019 3
  3263. a1021 2
  3264.      case SIOCSDPITIMEO:    /* Set Timeouts */
  3265.     dp_settimos(&dupii[ifp->if_unit], (u_long *)ifr->ifr_data);
  3266. d1023 3
  3267. a1025 2
  3268.      case SIOCGDPITIMEO:    /* Get Timeouts */
  3269.     dp_gettimos(&dupii[ifp->if_unit], (u_long *)ifr->ifr_data);
  3270. d1028 9
  3271. d1045 1
  3272. a1045 1
  3273. dp_settimos(p, to)
  3274. d1048 1
  3275. d1051 1
  3276. a1051 1
  3277.     for (t = 0 ; t < DP_NTIMEOUTS ; t++)
  3278. @
  3279.  
  3280.  
  3281. 1.12
  3282. log
  3283. @New duipreq calling sequence.
  3284. @
  3285. text
  3286. @d47 3
  3287. d54 2
  3288. d64 1
  3289. d73 1
  3290. d104 5
  3291. a108 3
  3292.     DP_DEF_INACT / DP_HZ,        /* Activity Timeout */
  3293.     DP_DEF_WAIT  / DP_HZ,        /* Call Wait Timeout */
  3294.     DP_DEF_FAIL  / DP_HZ,        /* Failed Call Timeout */
  3295. d113 6
  3296. d156 1
  3297. a156 2
  3298.     p->pii_timer = -1;
  3299.     p->pii_dustate = PII_DPS_DISCON;
  3300. d195 3
  3301. d225 1
  3302. a225 1
  3303.         p->pii_dustate = PII_DPS_DISCON;
  3304. d285 2
  3305. a286 2
  3306.         p->pii_dustate = PII_DPS_ACTIVE;
  3307.         dp_start(p);
  3308. d300 1
  3309. a300 2
  3310.         p->pii_dustate = PII_DPS_FAILCALL;
  3311.         dp_settimer(p);
  3312. d314 1
  3313. a314 2
  3314.         p->pii_dustate = PII_DPS_WAITING;
  3315.         dp_settimer(p);
  3316. d446 1
  3317. a446 1
  3318.         dp_callstat(p, *mp->b_cont->b_rptr);
  3319. a504 1
  3320.     dp_settimer(p);
  3321. d557 1
  3322. a557 1
  3323.     register mblk_t *mp,*m0;
  3324. d708 5
  3325. d797 1
  3326. a797 2
  3327.     p->pii_dustate = PII_DPS_WAITING;
  3328.     dp_settimer(p);
  3329. a874 1
  3330.     int n = 0;
  3331. a877 1
  3332.     n++;
  3333. d896 3
  3334. a949 1
  3335.     dp_settimer(p);
  3336. d1040 1
  3337. a1040 1
  3338.     if (to[t] != DP_DEF_TIMEOUT) {
  3339. d1042 13
  3340. a1054 6
  3341.         if (p->pii_dustate == t &&
  3342.         p->pii_timer > p->pii_timo[t])
  3343.         p->pii_timer = p->pii_timo[t];
  3344.     }
  3345.     DLOG3("dp_settimos: timeouts %d %d %d\n", p->pii_timo[0] * DP_HZ,
  3346.       p->pii_timo[1] * DP_HZ, p->pii_timo[2] * DP_HZ);
  3347. d1064 3
  3348. a1066 2
  3349.     DLOG3("dp_gettimos: timeouts %d %d %d\n", p->pii_timo[0] * DP_HZ,
  3350.       p->pii_timo[1] * DP_HZ, p->pii_timo[2] * DP_HZ);
  3351. d1069 1
  3352. a1069 1
  3353. dp_settimer(p)
  3354. d1071 1
  3355. d1073 6
  3356. a1078 3
  3357.     p->pii_ifnet.if_timer = (p->pii_timer = p->pii_timo[p->pii_dustate])
  3358.               ? DP_HZ
  3359.               : 0;
  3360. d1081 15
  3361. d1112 20
  3362. a1131 1
  3363.     if (p->pii_timer > 0 && --(p->pii_timer)) {
  3364. d1138 4
  3365. d1153 1
  3366. a1153 1
  3367.     p->pii_dustate = PII_DPS_FAILCALL;
  3368. d1162 1
  3369. a1162 1
  3370.     p->pii_dustate = PII_DPS_DISCON;
  3371. d1171 1
  3372. a1171 1
  3373.     p->pii_dustate = PII_DPS_DISCON;
  3374. a1177 1
  3375.     dp_settimer(p);
  3376. d1181 130
  3377. d1312 35
  3378. @
  3379.  
  3380.  
  3381. 1.11
  3382. log
  3383. @Fixed "panic: mclput" bug by being more careful about calling m_pullup
  3384. (and fixed possible panic when m_pullup fails).
  3385.  
  3386. @
  3387. text
  3388. @d763 1
  3389. a763 1
  3390.         if (duipreq(mtod(m0, struct ip *), dst, ifp)) {
  3391. d836 2
  3392. a837 1
  3393.     m_freem(m0);
  3394. @
  3395.  
  3396.  
  3397. 1.10
  3398. log
  3399. @Reorganized timeout mechanism.
  3400. @
  3401. text
  3402. @d866 2
  3403. d871 7
  3404. a877 1
  3405.         m0 = m_pullup(m0, sizeof(struct ip));
  3406. @
  3407.  
  3408.  
  3409. 1.9
  3410. log
  3411. @Count outgoing packets only once.
  3412. @
  3413. text
  3414. @d50 3
  3415. a53 2
  3416.     "WAITING",
  3417.     "ACTIVE",
  3418. a54 1
  3419.     "FAILCALL",
  3420. d58 1
  3421. d66 1
  3422. d96 7
  3423. d129 1
  3424. d139 2
  3425. a140 3
  3426.     p->pii_atimo = DP_DEF_INACT/DP_HZ;
  3427.     p->pii_wtimo = DP_DEF_WAIT/DP_HZ;
  3428.     p->pii_ftimo = DP_DEF_FAIL/DP_HZ;
  3429. d142 3
  3430. a237 20
  3431. static
  3432. dp_ioc_gint(q, mp, i, val)
  3433. queue_t    *q;
  3434. register mblk_t *mp;
  3435. register struct iocblk *i;
  3436. int val;
  3437. {
  3438.     if (mp->b_cont = allocb(sizeof(int), BPRI_MED)) {
  3439.     *(int *)mp->b_cont->b_wptr = val;
  3440.     mp->b_cont->b_wptr += i->ioc_count  = sizeof(int);
  3441.     mp->b_datap->db_type = M_IOCACK;
  3442.     }
  3443.     else {
  3444.     i->ioc_error = ENOSR;
  3445.     i->ioc_count = 0;
  3446.     mp->b_datap->db_type = M_IOCNAK;
  3447.     }
  3448.     qreply(q, mp);
  3449. }
  3450.  
  3451. d385 2
  3452. a386 1
  3453.         if (dp_ioc_sint(mp, i, &x))
  3454. d388 2
  3455. d407 11
  3456. a417 1
  3457.         dp_ioc_gint(q, mp, i, p->pii_ifnet.if_unit);
  3458. d438 3
  3459. a440 3
  3460.      case SIOCSDPATIMEO:    /* Set Activity Timeout */
  3461.         DLOG("dp_if: SIFSDPATIMEO %d\n", *(int *)mp->b_cont->b_rptr);
  3462.         if (dp_ioc_sint(mp, i, &x))
  3463. d442 2
  3464. a443 8
  3465.         p->pii_atimo = x / DP_HZ;
  3466.         if (p->pii_dustate == PII_DPS_ACTIVE &&
  3467.         p->pii_timer > p->pii_atimo)
  3468.         p->pii_timer = p->pii_atimo;
  3469.         goto iocack;
  3470.      case SIOCGDPATIMEO:    /* Get Activity Timeout */
  3471.         DLOG("dp_if: SIFGDPATIMEO %d\n", p->pii_atimo * DP_HZ);
  3472.         dp_ioc_gint(q, mp, i, p->pii_atimo * DP_HZ);
  3473. d445 13
  3474. a457 13
  3475.  
  3476.      case SIOCSDPWTIMEO:    /* Set Dial Wait Timeout */
  3477.         DLOG("dp_if: SIFSDPWTIMEO %d\n", *(int *)mp->b_cont->b_rptr);
  3478.         if (dp_ioc_sint(mp, i, &x))
  3479.         goto iocnak;
  3480.         p->pii_wtimo = x / DP_HZ;
  3481.         if (p->pii_dustate == PII_DPS_ACTIVE &&
  3482.         p->pii_timer > p->pii_wtimo)
  3483.         p->pii_timer = p->pii_wtimo;
  3484.         goto iocack;
  3485.      case SIOCGDPWTIMEO:    /* Get Dial Wait Timeout */
  3486.         DLOG("dp_if: SIFGDPATIMEO %d\n", p->pii_wtimo * DP_HZ);
  3487.         dp_ioc_gint(q, mp, i, p->pii_wtimo * DP_HZ);
  3488. a459 15
  3489.      case SIOCSDPFTIMEO:    /* Set Failed Call Timeout */
  3490.         DLOG("dp_if: SIFSDPFTIMEO %d\n", *(int *)mp->b_cont->b_rptr);
  3491.         if (dp_ioc_sint(mp, i, &x))
  3492.         goto iocnak;
  3493.         p->pii_ftimo = x / DP_HZ;
  3494.         if (p->pii_dustate == PII_DPS_ACTIVE &&
  3495.         p->pii_timer > p->pii_ftimo)
  3496.         p->pii_timer = p->pii_ftimo;
  3497.         goto iocack;
  3498.      case SIOCGDPFTIMEO:    /* Get Failed Call Timeout */
  3499.         DLOG("dp_if: SIFGDPATIMEO %d\n", p->pii_ftimo * DP_HZ);
  3500.         dp_ioc_gint(q, mp, i, p->pii_ftimo * DP_HZ);
  3501.         break;
  3502.  
  3503.  
  3504. d969 3
  3505. d987 3
  3506. a989 2
  3507.      case SIOCFAILCALL:
  3508.     dp_callstat(&dupii[ifp->if_unit], 0);
  3509. d991 8
  3510. d1007 27
  3511. d1037 3
  3512. a1039 18
  3513.     int thz = DP_HZ;
  3514.     switch (p->pii_dustate) {
  3515.      case PII_DPS_ACTIVE:
  3516.     p->pii_timer = p->pii_atimo;
  3517.     break;
  3518.      case PII_DPS_WAITING:
  3519.     p->pii_timer = p->pii_wtimo;
  3520.     break;
  3521.      case PII_DPS_FAILCALL:
  3522.     p->pii_timer = p->pii_ftimo;
  3523.     break;
  3524.      case PII_DPS_DOWN:
  3525.      case PII_DPS_DISCON:
  3526.     p->pii_timer = 0;
  3527.     thz = 0;
  3528.     break;
  3529.     }
  3530.     p->pii_ifnet.if_timer = thz;
  3531. a1087 5
  3532.  
  3533.     /*
  3534.      * XXX - add code to dig up queue structure and send M_SIG packet
  3535.      * upstream.
  3536.      */
  3537. @
  3538.  
  3539.  
  3540. 1.8
  3541. log
  3542. @Added options to callstat.
  3543. @
  3544. text
  3545. @a505 1
  3546.     p->pii_ifnet.if_opackets++; /* increment count of outgoing packets */
  3547. a506 1
  3548.     INCR(sl_opackets);
  3549. d932 1
  3550. d938 1
  3551. a940 1
  3552.     m_freem(m0);
  3553. @
  3554.  
  3555.  
  3556. 1.7
  3557. log
  3558. @Fixed problem if DEBUGS not defined.
  3559. @
  3560. text
  3561. @d60 1
  3562. a60 1
  3563. int    dp_if_debug=1;
  3564. d187 18
  3565. a204 13
  3566.     p->pii_flags &= ~PII_FLAGS_INUSE;
  3567.     switch (p->pii_dustate) {
  3568.      case PII_DPS_DOWN:
  3569.     break;
  3570.      case PII_DPS_DISCON:
  3571.      case PII_DPS_WAITING:
  3572.      case PII_DPS_ACTIVE:
  3573.      case PII_DPS_FAILCALL:
  3574.     p->pii_dustate = PII_DPS_DISCON;
  3575.     break;
  3576.      default:
  3577.     DLOG("dp_if_close: unknown state %d\n", p->pii_dustate);
  3578.     break;
  3579. d206 2
  3580. a207 3
  3581.     q->q_ptr = (char *)0;
  3582.     p->pii_writeq = (queue_t *)0;
  3583.     DLOG("dp_if%d: closed\n", (p-dupii)/sizeof(PII));
  3584. d265 11
  3585. a275 5
  3586.     if (p->pii_dustate == PII_DPS_WAITING)
  3587.     if (stat) {
  3588.         /*
  3589.          * Call succeeded.
  3590.          */
  3591. a276 1
  3592.         DLOGFLAGS("dp_callstat: call succeeded %x %x\n");
  3593. d278 1
  3594. d280 11
  3595. a290 4
  3596.     else {
  3597.         /*
  3598.          * Call failed.
  3599.          */
  3600. a292 1
  3601.         DLOGFLAGS("dp_callstat: call failed %x %x\n");
  3602. d294 1
  3603. d296 16
  3604. @
  3605.  
  3606.  
  3607. 1.6
  3608. log
  3609. @Removed clutter
  3610. @
  3611. text
  3612. @d604 1
  3613. d618 1
  3614. @
  3615.  
  3616.  
  3617. 1.5
  3618. log
  3619. @Renamed duppp to dp.
  3620. @
  3621. text
  3622. @a111 2
  3623. /*###112 [cc] undefined structure or union%%%*/
  3624. /*###112 [cc] warning: illegal member use: pii_flags%%%*/
  3625. a117 1
  3626. /*###118 [cc] undefined structure or union%%%*/
  3627. a118 1
  3628. /*###119 [cc] undefined structure or union%%%*/
  3629. @
  3630.  
  3631.  
  3632. 1.4
  3633. log
  3634. @Make it work almost..
  3635. @
  3636. text
  3637. @d1 1
  3638. a1 1
  3639. /* ppp_if.c - Streams PPP top level module handles if_ and packetizing PPP packets.
  3640. d8 2
  3641. a9 2
  3642. #include "duppp.h"
  3643. #if NDUPPP > 0
  3644. d46 1
  3645. a46 1
  3646. #include <sys/duppp_str.h>
  3647. d56 2
  3648. a57 2
  3649. #define    DLOG(s,a)    if (duppp_if_debug) log(LOG_INFO, s, a)
  3650. #define    DLOG2(s,a1,a2)    if (duppp_if_debug) log(LOG_INFO, s, a1, a2)
  3651. d59 2
  3652. a60 2
  3653. #define    DLOGSTATE(s)    if (duppp_if_debug) log(LOG_INFO, s, dus_str[p->pii_dustate])
  3654. int    duppp_if_debug=1;
  3655. d69 3
  3656. a71 3
  3657. static    int    duppp_if_open(), duppp_if_close(),
  3658.         duppp_if_rput(), duppp_if_wput(),
  3659.         duppp_if_wsrv(), duppp_if_rsrv();
  3660. d74 1
  3661. a74 1
  3662.     0xbad,"duppp_if",0, INFPSZ, 16384, 4096
  3663. d78 1
  3664. a78 1
  3665.     duppp_if_rput, duppp_if_rsrv, duppp_if_open, duppp_if_close, NULL, &minfo, NULL
  3666. d81 1
  3667. a81 1
  3668.     duppp_if_wput, duppp_if_wsrv, duppp_if_open, duppp_if_close, NULL, &minfo, NULL
  3669. d83 1
  3670. a83 1
  3671. struct    streamtab    duppp_ifinfo = {
  3672. d87 1
  3673. a87 1
  3674. typedef    struct duppp_if_info    PII;
  3675. d89 1
  3676. a89 1
  3677. PII    dupii[NDUPPP];
  3678. d91 2
  3679. a92 2
  3680. int    duppp_output(), duppp_ioctl();
  3681. static int duppp_start(), duppp_timer(), duppp_flush();
  3682. d96 1
  3683. a96 1
  3684. duppp_attach(unit)
  3685. d102 1
  3686. a102 1
  3687.     ifp->if_name = "duppp";
  3688. d106 2
  3689. a107 2
  3690.     ifp->if_ioctl  = duppp_ioctl;
  3691.     ifp->if_output = duppp_output;
  3692. d109 1
  3693. a109 1
  3694.     ifp->if_watchdog = duppp_timer;
  3695. d112 2
  3696. d117 1
  3697. a117 1
  3698. duppp_init(unit)
  3699. d120 1
  3700. d122 1
  3701. d133 3
  3702. a135 3
  3703.     p->pii_atimo = DUPPP_DEF_INACT/DUPPP_HZ;
  3704.     p->pii_wtimo = DUPPP_DEF_WAIT/DUPPP_HZ;
  3705.     p->pii_ftimo = DUPPP_DEF_FAIL/DUPPP_HZ;
  3706. d143 1
  3707. a143 1
  3708. duppp_if_open(q, dev, flag, sflag)
  3709. d156 1
  3710. a156 1
  3711. duppp_if_unit(q, unit)
  3712. d166 1
  3713. a166 1
  3714.     DLOG("duppp_if_unit: enter %d\n", unit);
  3715. d174 1
  3716. a174 1
  3717.     duppp_attach(unit); /* attach it */
  3718. d178 1
  3719. a178 1
  3720.     DLOG("duppp_if_unit: exit %d\n", unit);
  3721. d183 1
  3722. a183 1
  3723. duppp_if_close(q)
  3724. d190 1
  3725. a190 1
  3726.     duppp_flush(p, q);
  3727. d193 1
  3728. a193 1
  3729.      case PII_DUS_DOWN:
  3730. d195 5
  3731. a199 5
  3732.      case PII_DUS_DISCON:
  3733.      case PII_DUS_WAITING:
  3734.      case PII_DUS_ACTIVE:
  3735.      case PII_DUS_FAILCALL:
  3736.     p->pii_dustate = PII_DUS_DISCON;
  3737. d202 1
  3738. a202 1
  3739.     DLOG("duppp_if_close: unknown state %d\n", p->pii_dustate);
  3740. d207 1
  3741. a207 1
  3742.     DLOG("duppp_if%d: closed\n", (p-dupii)/sizeof(PII));
  3743. d213 1
  3744. a213 1
  3745. duppp_flush(p, q)
  3746. d227 1
  3747. a227 1
  3748. duppp_ioc_gint(q, mp, i, val)
  3749. d247 1
  3750. a247 1
  3751. duppp_ioc_sint(mp, i, valp)
  3752. d261 1
  3753. a261 1
  3754. duppp_callstat(p, stat)
  3755. d265 1
  3756. a265 1
  3757.     if (p->pii_dustate == PII_DUS_WAITING)
  3758. d270 3
  3759. a272 3
  3760.         p->pii_dustate = PII_DUS_ACTIVE;
  3761.         DLOGFLAGS("duppp_callstat: call succeeded %x %x\n");
  3762.         duppp_start(p);
  3763. d278 4
  3764. a281 4
  3765.         p->pii_dustate = PII_DUS_FAILCALL;
  3766.         duppp_settimer(p);
  3767.         DLOGFLAGS("duppp_callstat: call failed %x %x\n");
  3768.         duppp_flush(p, p->pii_writeq);
  3769. d286 1
  3770. a286 1
  3771. duppp_if_wput(q, mp)
  3772. d323 1
  3773. a323 1
  3774.         DLOG("duppp_if: SIFCOMPAC %d\n",  *(u_char *) mp->b_cont->b_rptr);
  3775. d331 1
  3776. a331 1
  3777.         DLOG("duppp_if: SIFCOMPPROT %d\n",  *(u_char *) mp->b_cont->b_rptr);
  3778. d344 1
  3779. a344 1
  3780.         DLOG("duppp_if: SIFVJCOMP %d\n",  *(u_char *) mp->b_cont->b_rptr);
  3781. d362 1
  3782. a362 1
  3783.         DLOG2("duppp_if: SIFSIFUNIT %d p %x\n",
  3784. d364 1
  3785. a364 1
  3786.         if (duppp_ioc_sint(mp, i, &x))
  3787. d366 1
  3788. a366 1
  3789.         if (x < 0 || x > NDUPPP || q->q_ptr) {
  3790. d374 3
  3791. a376 3
  3792.         DLOG2("before duppp_if_unit %x %x\n", q, mp);
  3793.         duppp_if_unit(q, x);
  3794.         DLOG2("after  duppp_if_unit %x %x\n", q, mp);
  3795. d382 2
  3796. a383 2
  3797.         DLOG("duppp_if: SIFGIFUNIT %d\n", p->pii_ifnet.if_unit);
  3798.         duppp_ioc_gint(q, mp, i, p->pii_ifnet.if_unit);
  3799. d387 1
  3800. a387 1
  3801.         DLOG("duppp_if: SIFCALLSTAT %d\n", *(char *)mp->b_cont->b_rptr);
  3802. d397 1
  3803. a397 1
  3804.         duppp_callstat(p, *mp->b_cont->b_rptr);
  3805. d404 3
  3806. a406 3
  3807.      case SIOCSDUATIMEO:    /* Set Activity Timeout */
  3808.         DLOG("duppp_if: SIFSDUATIMEO %d\n", *(int *)mp->b_cont->b_rptr);
  3809.         if (duppp_ioc_sint(mp, i, &x))
  3810. d408 2
  3811. a409 2
  3812.         p->pii_atimo = x / DUPPP_HZ;
  3813.         if (p->pii_dustate == PII_DUS_ACTIVE &&
  3814. d413 3
  3815. a415 3
  3816.      case SIOCGDUATIMEO:    /* Get Activity Timeout */
  3817.         DLOG("duppp_if: SIFGDUATIMEO %d\n", p->pii_atimo * DUPPP_HZ);
  3818.         duppp_ioc_gint(q, mp, i, p->pii_atimo * DUPPP_HZ);
  3819. d418 3
  3820. a420 3
  3821.      case SIOCSDUWTIMEO:    /* Set Dial Wait Timeout */
  3822.         DLOG("duppp_if: SIFSDUWTIMEO %d\n", *(int *)mp->b_cont->b_rptr);
  3823.         if (duppp_ioc_sint(mp, i, &x))
  3824. d422 2
  3825. a423 2
  3826.         p->pii_wtimo = x / DUPPP_HZ;
  3827.         if (p->pii_dustate == PII_DUS_ACTIVE &&
  3828. d427 3
  3829. a429 3
  3830.      case SIOCGDUWTIMEO:    /* Get Dial Wait Timeout */
  3831.         DLOG("duppp_if: SIFGDUATIMEO %d\n", p->pii_wtimo * DUPPP_HZ);
  3832.         duppp_ioc_gint(q, mp, i, p->pii_wtimo * DUPPP_HZ);
  3833. d432 3
  3834. a434 3
  3835.      case SIOCSDUFTIMEO:    /* Set Failed Call Timeout */
  3836.         DLOG("duppp_if: SIFSDUFTIMEO %d\n", *(int *)mp->b_cont->b_rptr);
  3837.         if (duppp_ioc_sint(mp, i, &x))
  3838. d436 2
  3839. a437 2
  3840.         p->pii_ftimo = x / DUPPP_HZ;
  3841.         if (p->pii_dustate == PII_DUS_ACTIVE &&
  3842. d441 3
  3843. a443 3
  3844.      case SIOCGDUFTIMEO:    /* Get Failed Call Timeout */
  3845.         DLOG("duppp_if: SIFGDUATIMEO %d\n", p->pii_ftimo * DUPPP_HZ);
  3846.         duppp_ioc_gint(q, mp, i, p->pii_ftimo * DUPPP_HZ);
  3847. d451 1
  3848. a451 1
  3849.     DLOG("duppp_if_wput: Pii->flags %x\n", p->pii_flags);
  3850. d460 1
  3851. a460 1
  3852. duppp_if_wsrv(q)
  3853. d478 1
  3854. a478 1
  3855.     duppp_settimer(p);
  3856. d485 1
  3857. a485 1
  3858. duppp_if_rput(q, mp)
  3859. d510 1
  3860. a510 1
  3861.         DLOG("duppp_if: input error inc to %d\n", p->pii_ifnet.if_ierrors);
  3862. d515 1
  3863. a515 1
  3864.         DLOG("duppp_if: output error inc to %d\n", p->pii_ifnet.if_oerrors);
  3865. d529 1
  3866. a529 1
  3867. duppp_if_rsrv(q)
  3868. d583 1
  3869. a583 1
  3870.             DLOG("ppp: sl_uncompress failed on type Compressed",0);;
  3871. d598 1
  3872. a598 1
  3873.         DLOG("ppp: sl_uncompress failed on type Uncompresed\n",0);
  3874. d608 1
  3875. a608 1
  3876.         if (duppp_if_debug) {
  3877. d611 1
  3878. a611 1
  3879.             DLOG("ppp: LCP packet 0x%x\n", ntohs(ph->ph_protocol));
  3880. d614 1
  3881. a614 1
  3882.             DLOG("ppp: NCP packet 0x%x\n", ntohs(ph->ph_protocol));
  3883. d617 1
  3884. a617 1
  3885.             DLOG("ppp: unknown protocol 0x%x\n",
  3886. d698 1
  3887. a698 1
  3888. duppp_output(ifp, m0, dst)
  3889. d708 1
  3890. a708 1
  3891.     DLOG2("duppp_output: state %s flags %x\n", dus_str[p->pii_dustate], p->pii_flags);
  3892. d717 1
  3893. a717 1
  3894.      case PII_DUS_ACTIVE:
  3895. d724 2
  3896. a725 2
  3897.      case PII_DUS_DOWN:
  3898.      case PII_DUS_FAILCALL:
  3899. d730 1
  3900. a730 1
  3901.     DLOGSTATE("ppp_output: NETDOWN %s\n");
  3902. d734 1
  3903. a734 1
  3904.      case PII_DUS_WAITING:
  3905. d739 1
  3906. a739 1
  3907.     DLOGFLAGS("ppp_output: DUS_WAITING %x %x\n");
  3908. d742 1
  3909. a742 1
  3910.      case PII_DUS_DISCON:
  3911. d751 1
  3912. a751 1
  3913.         DLOGFLAGS("ppp_output: duipreq failed %x %x\n");
  3914. d761 1
  3915. a761 1
  3916.         DLOGFLAGS("ppp_output: DISCON bad family %x %x\n");
  3917. d765 3
  3918. a767 3
  3919.     p->pii_dustate = PII_DUS_WAITING;
  3920.     duppp_settimer(p);
  3921.     DLOGFLAGS("ppp_output: duipreq in progress %x %x\n");
  3922. d771 1
  3923. a771 1
  3924.     DLOG("duppp_output: unknown state %d\n", p->pii_dustate);
  3925. d788 1
  3926. a788 1
  3927.     printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
  3928. d815 1
  3929. a815 1
  3930.     error = duppp_start(p);
  3931. d832 1
  3932. a832 1
  3933. duppp_start(p)
  3934. d846 1
  3935. a846 1
  3936.        (p->pii_dustate == PII_DUS_ACTIVE)) {
  3937. d918 1
  3938. a918 1
  3939. duppp_ioctl(ifp, cmd, data)
  3940. d941 1
  3941. a941 1
  3942.     duppp_init(ifp->if_unit);
  3943. d971 1
  3944. a971 1
  3945.     duppp_callstat(&dupii[ifp->if_unit], 0);
  3946. d981 1
  3947. a981 1
  3948. duppp_settimer(p)
  3949. d984 1
  3950. a984 1
  3951.     int thz = DUPPP_HZ;
  3952. d986 1
  3953. a986 1
  3954.      case PII_DUS_ACTIVE:
  3955. d989 1
  3956. a989 1
  3957.      case PII_DUS_WAITING:
  3958. d992 1
  3959. a992 1
  3960.      case PII_DUS_FAILCALL:
  3961. d995 2
  3962. a996 2
  3963.      case PII_DUS_DOWN:
  3964.      case PII_DUS_DISCON:
  3965. d1008 1
  3966. a1008 1
  3967. duppp_timer(unit)
  3968. d1015 1
  3969. a1015 1
  3970.     DLOGSTATE("duppp_timer: before %s\n");
  3971. d1022 1
  3972. a1022 1
  3973.     p->pii_ifnet.if_timer = DUPPP_HZ;
  3974. d1028 2
  3975. a1029 2
  3976.      case PII_DUS_DOWN:
  3977.      case PII_DUS_DISCON:
  3978. d1034 1
  3979. a1034 1
  3980.      case PII_DUS_WAITING:
  3981. d1038 3
  3982. a1040 3
  3983.     p->pii_dustate = PII_DUS_FAILCALL;
  3984.     duppp_flush(p, q);
  3985.     DLOG("duppp_timer: unit %d - we never had a line.\n", unit);
  3986. d1043 1
  3987. a1043 1
  3988.      case PII_DUS_ACTIVE:
  3989. d1047 2
  3990. a1048 2
  3991.     p->pii_dustate = PII_DUS_DISCON;
  3992.     DLOG("duppp_timer: sending SIGTERM to PPP process\n", unit);
  3993. d1057 1
  3994. a1057 1
  3995.      case PII_DUS_FAILCALL:
  3996. d1061 1
  3997. a1061 1
  3998.     p->pii_dustate = PII_DUS_DISCON;
  3999. d1065 1
  4000. a1065 1
  4001.     DLOG("duppp_timer: unknown state %d\n", p->pii_dustate);
  4002. d1068 1
  4003. a1068 1
  4004.     duppp_settimer(p);
  4005. d1070 1
  4006. a1070 1
  4007.     DLOGSTATE("duppp_timer: after %s\n");
  4008. @
  4009.  
  4010.  
  4011. 1.3
  4012. log
  4013. @Lots of fixes, and some debug statements.
  4014. @
  4015. text
  4016. @d61 1
  4017. d92 1
  4018. a92 1
  4019. static int duppp_start(), duppp_timer();
  4020. d171 2
  4021. a172 3
  4022.     p->pii_writeq = WR(q);
  4023.     WR(q)->q_ptr = q->q_ptr = (caddr_t) p;    /* set write Q and read Q to point here */
  4024.     p->pii_q = q;
  4025. d186 1
  4026. a186 1
  4027.     duppp_flush(p);
  4028. d202 1
  4029. a202 1
  4030.     p->pii_q = (queue_t *)0;
  4031. d208 2
  4032. a209 1
  4033. duppp_flush(p)
  4034. d211 1
  4035. d213 2
  4036. a214 2
  4037.     queue_t *q = p->pii_q;
  4038.  
  4039. d217 1
  4040. a217 1
  4041.     flushq(WR(q), FLUSHALL);
  4042. a218 1
  4043.     if_qflush(&p->pii_ifnet.if_snd);
  4044. d277 1
  4045. a277 1
  4046.         duppp_flush(p);
  4047. d373 1
  4048. a386 1
  4049.         DLOG2("duppp_wput: iocnak qreply(%x,%x)\n", q, mp);
  4050. a389 1
  4051.         DLOG("duppp_wput: iocnak after qreply\n", i->ioc_error);
  4052. a395 1
  4053.         DLOG2("duppp_wput: iocack qreply(%x,%x)\n", q, mp);
  4054. a397 1
  4055.         DLOG("duppp_wput: iocack after qreply (%d)\n", i->ioc_error);
  4056. d839 1
  4057. d843 1
  4058. d1008 1
  4059. a1008 1
  4060.     queue_t *q = p->pii_q;
  4061. d1019 1
  4062. d1035 1
  4063. a1035 1
  4064.     duppp_flush(p);
  4065. d1044 2
  4066. a1045 1
  4067.     putctl1(q, M_SIG, SIGTERM);
  4068. @
  4069.  
  4070.  
  4071. 1.2
  4072. log
  4073. @Added stuff for dialup.
  4074. @
  4075. text
  4076. @a49 1
  4077.     "Uninitialized",
  4078. d88 1
  4079. a88 1
  4080. PII    pii[NDUPPP];
  4081. d96 1
  4082. a96 1
  4083.     int    unit;
  4084. d98 2
  4085. a99 1
  4086.     register struct ifnet *ifp = &pii[unit].pii_ifnet;
  4087. d111 1
  4088. a111 1
  4089.     pii[unit].pii_flags |= PII_FLAGS_ATTACHED;
  4090. d114 5
  4091. d120 17
  4092. d146 1
  4093. a146 1
  4094.     return(OPENFAIL);
  4095. d148 1
  4096. d159 1
  4097. a159 1
  4098.     p = &pii[unit];
  4099. d161 1
  4100. a161 1
  4101.     DLOG("duppp_if_unit: %d", unit);
  4102. d174 1
  4103. a174 8
  4104.     DLOG("duppp_if_unit: %d\n", unit);
  4105.     if (!p->pii_dustate) {
  4106.     p->pii_dustate = PII_DUS_DISCON;
  4107.     p->pii_atimo = DUPPP_DEF_INACT/DUPPP_HZ;
  4108.     p->pii_wtimo = DUPPP_DEF_WAIT/DUPPP_HZ;
  4109.     p->pii_ftimo = DUPPP_DEF_FAIL/DUPPP_HZ;
  4110.     p->pii_timer = -1;
  4111.     }
  4112. d186 1
  4113. a186 1
  4114.     duppp_flush(q);
  4115. d203 1
  4116. a203 1
  4117.     DLOG("duppp_if%d: closed\n", (p-pii)/sizeof(PII));
  4118. d208 2
  4119. a209 2
  4120. duppp_flush(q)
  4121. queue_t    *q;
  4122. d211 1
  4123. a211 2
  4124.     register PII *p;
  4125.     register int s;
  4126. d213 4
  4127. a216 3
  4128.     p = (PII *) q->q_ptr;
  4129.     flushq(q, FLUSHALL);
  4130.     flushq(WR(q), FLUSHALL);
  4131. d256 25
  4132. d288 1
  4133. a288 1
  4134.     register int x;
  4135. d311 1
  4136. a311 1
  4137.     if (!q->q_ptr && i->ioc_cmd != SIOCSIFUNIT)
  4138. d350 1
  4139. a350 1
  4140.         qreply(q,mp);
  4141. d357 2
  4142. d369 1
  4143. d371 1
  4144. a373 1
  4145.  
  4146. d376 1
  4147. d381 1
  4148. d384 3
  4149. a386 1
  4150. iocnak:        i->ioc_count = 0;
  4151. d389 1
  4152. d392 6
  4153. a397 23
  4154.         if (p->pii_dustate == PII_DUS_WAITING)
  4155.         if (*mp->b_cont->b_rptr) {
  4156.             /*
  4157.              * Call succeeded.
  4158.              */
  4159.             p->pii_dustate = PII_DUS_ACTIVE;
  4160.             DLOGFLAGS("duppp_if_wput: call succeeded %x %x\n");
  4161.             x = splimp();
  4162.             duppp_start(p);
  4163.             splx(x);
  4164.         }
  4165.         else {
  4166.             /*
  4167.              * Call failed.
  4168.              */
  4169.             p->pii_dustate = PII_DUS_FAILCALL;
  4170.             duppp_settimer(p);
  4171.             DLOGFLAGS("duppp_if_wput: call failed %x %x\n");
  4172.             x = splimp();
  4173.             duppp_flush(p);
  4174.             splx(x);
  4175.         }
  4176. iocack:        mp->b_datap->db_type = M_IOCACK;
  4177. d399 1
  4178. d403 1
  4179. d412 1
  4180. d417 1
  4181. d426 1
  4182. d431 1
  4183. d440 1
  4184. d449 1
  4185. a449 1
  4186.     DLOG("ppp: Pii->flags 0x%x\n",p->pii_flags);
  4187. d701 1
  4188. a701 1
  4189.     register PII    *p = &pii[ifp->if_unit];
  4190. d703 2
  4191. a704 2
  4192.     int    error,s, len;
  4193.     u_short    protocol;
  4194. d706 1
  4195. a706 1
  4196.     DLOG("ppp_output: unit %x\n", ifp->if_unit);
  4197. d709 1
  4198. a709 1
  4199.     if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) {
  4200. d728 1
  4201. d759 1
  4202. a835 1
  4203.     int error = 0;
  4204. d937 1
  4205. d966 3
  4206. d1007 1
  4207. a1007 1
  4208.     register PII *p = &pii[unit];
  4209. a1010 1
  4210.     DLOG("duppp_timer: unit = %d\n", unit);
  4211. d1034 1
  4212. a1034 1
  4213.     duppp_flush(q);
  4214. @
  4215.  
  4216.  
  4217. 1.1
  4218. log
  4219. @Initial revision
  4220. @
  4221. text
  4222. @d8 2
  4223. a9 2
  4224. #include "ppp.h"
  4225. #if NPPP > 0
  4226. d14 1
  4227. a15 1
  4228. #define    DEBUGS    1
  4229. d28 1
  4230. d46 1
  4231. a46 1
  4232. #include <sys/ppp_str.h>
  4233. d49 13
  4234. a61 2
  4235. #define    DLOG(s,a)    if(ppp_if_debug) log(LOG_INFO, s, a)
  4236. int    ppp_if_debug=0;
  4237. d63 4
  4238. a66 1
  4239. #define    DLOG(s)    {}
  4240. d69 3
  4241. a71 2
  4242. static    int    ppp_if_open(), ppp_if_close(), ppp_if_rput(), ppp_if_wput(),
  4243.         ppp_if_wsrv(), ppp_if_rsrv();
  4244. d74 1
  4245. a74 1
  4246.     0xbad,"ppp_if",0, INFPSZ, 16384, 4096
  4247. d78 1
  4248. a78 1
  4249.     ppp_if_rput, ppp_if_rsrv, ppp_if_open, ppp_if_close, NULL, &minfo, NULL
  4250. d81 1
  4251. a81 1
  4252.     ppp_if_wput, ppp_if_wsrv, ppp_if_open, ppp_if_close, NULL, &minfo, NULL
  4253. d83 1
  4254. a83 1
  4255. struct    streamtab    ppp_ifinfo = {
  4256. d87 1
  4257. a87 15
  4258. #ifdef    OLD
  4259. struct    ppp_if_info {
  4260.     int    pii_flags;
  4261. #define    PII_FLAGS_INUSE        0x1        /* in use by  a stream    */
  4262. #define    PII_FLAGS_COMPAC    0x2
  4263. #define    PII_FLAGS_COMPPROT    0x4
  4264. #define    PII_FLAGS_ATTACHED    0x8        /* already if_attached    */
  4265. #define    PII_FLAGS_VJC_ON    0x10        /* VJ TCP header compression enabled */
  4266.     struct    ifnet    pii_ifnet;
  4267.     queue_t        *pii_writeq;        /* used by ppp_output     */
  4268. #ifdef    VJC
  4269.     struct     slcompress    pii_sc_comp;    /* vjc control buffer */
  4270. #endif
  4271. };
  4272. #endif
  4273. d89 1
  4274. a89 1
  4275. typedef    struct ppp_if_info    PII;
  4276. d91 2
  4277. a92 1
  4278. PII    pii[NPPP];
  4279. a93 1
  4280. int    ppp_output(), ppp_ioctl();
  4281. a94 1
  4282.  
  4283. d96 1
  4284. a96 1
  4285. ppp_attach(unit)
  4286. d99 1
  4287. a99 1
  4288.     register struct ifnet *ifp = &pii[unit].pii_ifnet;
  4289. d101 11
  4290. a111 9
  4291.     ifp->if_name = "ppp";
  4292.     ifp->if_mtu  = PPP_MTU;
  4293.     ifp->if_flags = IFF_POINTOPOINT;
  4294.     ifp->if_unit  = unit;
  4295.     ifp->if_ioctl    = ppp_ioctl;
  4296.     ifp->if_output    = ppp_output;
  4297.     ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  4298.     if_attach(ifp);
  4299.     pii[unit].pii_flags |= PII_FLAGS_ATTACHED;
  4300. d116 11
  4301. a126 5
  4302. ppp_if_open(q, dev, flag, sflag)
  4303.     queue_t    *q;
  4304.     dev_t    dev;
  4305.     int    flag,
  4306.         sflag;
  4307. d128 3
  4308. d132 2
  4309. a133 3
  4310.     register PII    *p;
  4311.     register int    x;
  4312.     int    s;
  4313. d135 4
  4314. a138 9
  4315.     if(!suser()) {
  4316.         u.u_error = EPERM;
  4317.         return(OPENFAIL);
  4318.     }
  4319.     s = splstr();
  4320.     if(!q->q_ptr) {
  4321.         for(x=0; x < NPPP; x++) {
  4322.             if(!(pii[x].pii_flags & PII_FLAGS_INUSE)) {    /* we can use it */
  4323.                 p = &pii[x];
  4324. d141 1
  4325. a141 1
  4326.                 bzero(&p->pii_stats,sizeof(p->pii_stats));
  4327. d143 1
  4328. a143 8
  4329. #ifdef    JUNK
  4330.                 if(!p->pii_sc_comp) {
  4331.                     p->pii_sc_comp = (struct slcompress *) kmem_alloc(sizeof(struct slcompress));
  4332.                     if(!p->pii_sc_comp) {
  4333.                         u.u_error = ENOSR;
  4334.                         return(OPENFAIL);
  4335.                     }
  4336.                 }
  4337. d145 15
  4338. a159 43
  4339.                 sl_compress_init(&p->pii_sc_comp);
  4340. #endif
  4341.                 if(!(p->pii_flags & PII_FLAGS_ATTACHED))
  4342.                     ppp_attach(x);            /* attach it */
  4343.                 p->pii_writeq = WR(q);
  4344.                 WR(q)->q_ptr = q->q_ptr = (caddr_t) p;    /* set write Q and read Q to point here */
  4345.                 p->pii_ifnet.if_flags |= IFF_RUNNING;
  4346.                 p->pii_flags = PII_FLAGS_INUSE|PII_FLAGS_ATTACHED;
  4347.                 DLOG("ppp_if%d: open\n",x);
  4348.                 splx(s);
  4349.                 return(x);
  4350.             }
  4351.         }
  4352.     }
  4353.     else {
  4354.         p = (PII *) q->q_ptr;
  4355. #ifdef    VJC
  4356. #ifdef    PPP_STATS
  4357.         bzero(&p->pii_stats,sizeof(p->pii_stats));
  4358. #endif
  4359. #ifdef    JUNK
  4360.         if(!p->pii_sc_comp) {
  4361.             p->pii_sc_comp = (struct slcompress *) kmem_alloc(sizeof(struct slcompress));
  4362.             if(!p->pii_sc_comp) {
  4363.                 u.u_error = ENOSR;
  4364.                 return(OPENFAIL);
  4365.             }
  4366.         }
  4367. #endif
  4368.         sl_compress_init(&p->pii_sc_comp);
  4369. #endif
  4370.         DLOG("ppp_if%d: reopen\n", (p-pii)/sizeof(PII));
  4371.         if(!(p->pii_flags & PII_FLAGS_ATTACHED))
  4372.             ppp_attach(x);            /* attach it */
  4373.         p->pii_writeq = WR(q);
  4374.         WR(q)->q_ptr = q->q_ptr = (caddr_t) p;    /* set write Q and read Q to point here */
  4375.         p->pii_ifnet.if_flags |= IFF_RUNNING;
  4376.         p->pii_flags = PII_FLAGS_INUSE|PII_FLAGS_ATTACHED;
  4377.         splx(s);
  4378.         return(0);
  4379.     }
  4380.     splx(s);
  4381.     return(OPENFAIL);
  4382. d163 1
  4383. a163 1
  4384. ppp_if_close(q)
  4385. d166 2
  4386. a167 2
  4387.     PII    *p = (PII *) q->q_ptr;
  4388.     int    s;
  4389. d169 21
  4390. a189 13
  4391.     s = splimp();
  4392.     p->pii_flags &= ~PII_FLAGS_INUSE;
  4393.     if_down(&p->pii_ifnet);
  4394.     p->pii_ifnet.if_flags &= ~IFF_RUNNING;
  4395. #ifdef    VJC
  4396. #ifdef    JUNK
  4397.     if(p->pii_sc_comp)
  4398.         kmem_free(p->pii_sc_comp);
  4399. #endif
  4400. #endif
  4401.     DLOG("ppp_if%d: closed\n", (p-pii)/sizeof(PII));
  4402.     splx(s);
  4403.     return(0);            /* no work to be done */
  4404. d192 5
  4405. d198 27
  4406. d226 4
  4407. a229 3
  4408. ppp_if_wput(q, mp)
  4409.     queue_t  *q;
  4410.     register mblk_t *mp;
  4411. d231 7
  4412. d239 5
  4413. a243 2
  4414.     register struct iocblk    *i;
  4415.     register PII    *p;
  4416. d245 3
  4417. a247 1
  4418.     switch (mp->b_datap->db_type) {
  4419. d249 6
  4420. a254 5
  4421.         case     M_FLUSH :
  4422.             if(*mp->b_rptr & FLUSHW)
  4423.                 flushq(q, FLUSHDATA);
  4424.             putnext(q, mp);        /* send it along too */
  4425.             break;
  4426. d256 10
  4427. a265 3
  4428.         case    M_DATA :
  4429.             putq(q, mp);    /* queue it for my service routine */
  4430.             break;
  4431. d267 5
  4432. a271 4
  4433.         case    M_IOCTL :
  4434.             i = (struct iocblk *) mp->b_rptr;
  4435.             p =  (PII *) q->q_ptr;
  4436.             switch (i->ioc_cmd) {
  4437. d273 20
  4438. a292 18
  4439.                 case SIOCSIFCOMPAC :    /* enable or disable AC compression */
  4440.                     if(i->ioc_count != sizeof(u_char)) 
  4441.                         goto passalong;
  4442.                     DLOG("ppp_if: SIFCOMPAC %d\n",  *(u_char *) mp->b_cont->b_rptr);
  4443.                     if( *(u_char *) mp->b_cont->b_rptr) 
  4444.                         p->pii_flags |= PII_FLAGS_COMPAC;
  4445.                     else
  4446.                         p->pii_flags &= ~PII_FLAGS_COMPAC;
  4447.                     goto passalong;
  4448.                 case SIOCSIFCOMPPROT:    /* enable or disable PROT  compression */
  4449.                     DLOG("ppp_if: SIFCOMPPROT %d\n",  *(u_char *) mp->b_cont->b_rptr);
  4450.                     if(i->ioc_count != sizeof(u_char))
  4451.                         goto passalong;
  4452.                     if( *(u_char *) mp->b_cont->b_rptr) 
  4453.                         p->pii_flags |= PII_FLAGS_COMPPROT;
  4454.                     else
  4455.                         p->pii_flags &= ~PII_FLAGS_COMPPROT;
  4456.                     goto passalong;
  4457. d294 1
  4458. a294 1
  4459.                 case SIOCSIFVJCOMP:    /* enable or disable VJ compression */
  4460. d296 8
  4461. a303 8
  4462.                     if(i->ioc_count != sizeof(u_char)) 
  4463.                         goto passalong;
  4464.                     DLOG("ppp_if: SIFVJCOMP %d\n",  *(u_char *) mp->b_cont->b_rptr);
  4465.                     if( *(u_char *) mp->b_cont->b_rptr) 
  4466.                         p->pii_flags |= PII_FLAGS_VJC_ON;
  4467.                     else
  4468.                         p->pii_flags &= ~PII_FLAGS_VJC_ON;
  4469.                     mp->b_datap->db_type = M_IOCACK;
  4470. d305 3
  4471. a307 3
  4472.                     mp->b_datap->db_type = M_IOCNAK;
  4473.                     i->ioc_error = EINVAL;
  4474.                     i->ioc_count = 0;
  4475. d309 2
  4476. a310 2
  4477.                     qreply(q,mp);
  4478.                     break;
  4479. d312 16
  4480. a327 22
  4481.                 case SIOCGETU :    /* get unit number */
  4482.                     if(mp->b_cont = allocb(sizeof(int), BPRI_MED)) {
  4483.                         *(int *) mp->b_cont->b_wptr = p->pii_ifnet.if_unit;
  4484.                         mp->b_cont->b_wptr += i->ioc_count  = sizeof(int);
  4485.                         mp->b_datap->db_type = M_IOCACK;
  4486.                         qreply(q,mp);
  4487.                         break;
  4488.                     }
  4489.                     i->ioc_error = ENOSR;
  4490.                     i->ioc_count = 0;
  4491.                     mp->b_datap->db_type = M_IOCNAK;
  4492.                     qreply(q, mp);
  4493.                     break;
  4494.                 default:        /* unknown IOCTL call */
  4495. passalong:;
  4496.                     putnext(q,mp);    /* pass it along */
  4497.             }
  4498.             DLOG("ppp: Pii->flags 0x%x\n",p->pii_flags);
  4499.             break;    
  4500.         default :
  4501.             putnext(q,mp);    /* don't know what to do with this, so send it along*/
  4502.     }
  4503. a328 1
  4504. }
  4505. d330 4
  4506. a333 6
  4507. static int
  4508. ppp_if_wsrv(q)
  4509.     queue_t    *q;
  4510. {
  4511.     register mblk_t *mp;
  4512.     register PII *p;
  4513. d335 18
  4514. a352 7
  4515.     p = (PII *) q->q_ptr;
  4516.  
  4517.     while((mp = getq(q)) != NULL) {
  4518.         /* we can only get M_DATA types into our Queue, due to our Put function */
  4519.         if(!canput(q->q_next)) {
  4520.             putbq(q, mp);
  4521.             return;
  4522. d354 14
  4523. a367 4
  4524.         p->pii_ifnet.if_opackets++;    /* increment count of outgoing packets */
  4525.         INCR(sl_opackets);
  4526.         putnext(q, mp);    /* just pass it along, nothing to do in this direction */
  4527.     }    /* end while */
  4528. d369 46
  4529. a417 1
  4530.  
  4531. d419 2
  4532. a420 3
  4533. ppp_if_rput(q, mp)
  4534.     queue_t *q;
  4535.     register mblk_t *mp;
  4536. d422 2
  4537. d425 1
  4538. a425 2
  4539.     register u_char    *c;
  4540.     register PII    *p;
  4541. d427 15
  4542. a441 1
  4543.     switch (mp->b_datap->db_type) {
  4544. d443 7
  4545. a449 5
  4546.         case     M_FLUSH :
  4547.             if(*mp->b_rptr & FLUSHR)
  4548.                 flushq(q, FLUSHDATA);
  4549.             putnext(q, mp);        /* send it along too */
  4550.             break;
  4551. d451 6
  4552. a456 3
  4553.         case    M_DATA :
  4554.             putq(q, mp);    /* queue it for my service routine */
  4555.             break;
  4556. d458 20
  4557. a477 22
  4558.         case    M_CTL :        /* could be a message from below */
  4559.             p = (PII *) q->q_ptr;
  4560.             c = (u_char *) mp->b_rptr;
  4561.             switch  (c)    {
  4562.                 case IF_INPUT_ERROR :
  4563.                     p->pii_ifnet.if_ierrors++;
  4564.                     INCR(sl_ierrors);
  4565.                     DLOG("ppp_if: input error inc to %d\n", p->pii_ifnet.if_ierrors);
  4566.                     break;
  4567.                 case IF_OUTPUT_ERROR :
  4568.                     p->pii_ifnet.if_oerrors++;
  4569.                     INCR(sl_oerrors);
  4570.                     DLOG("ppp_if: output error inc to %d\n", p->pii_ifnet.if_oerrors);
  4571.                     break;
  4572.                 default:;
  4573.                     break;
  4574.             }
  4575.             freemsg(mp);
  4576.             /* putnext(q, mp); */
  4577.             break;
  4578.         default :
  4579.             putnext(q,mp);    /* don't know what to do with this, so send it along*/
  4580. d479 6
  4581. d488 2
  4582. a489 2
  4583. ppp_if_rsrv(q)
  4584.     queue_t    *q;
  4585. d491 1
  4586. a491 1
  4587.     register mblk_t *mp,*m0;
  4588. d493 2
  4589. a494 2
  4590.     register mblk_t *mvjc;
  4591.     unsigned char *cp;
  4592. d497 6
  4593. a502 6
  4594.     register PII    *p;
  4595.     struct ifnet    **ifp;
  4596.     struct ppp_header    *ph;
  4597.     struct mbuf    *mb1, *mb2,*mbtail;
  4598.     int    len,xlen,count,s;
  4599.     u_char    *rptr;
  4600. d504 1
  4601. a504 1
  4602.     p = (PII *) q->q_ptr;
  4603. d506 24
  4604. a529 9
  4605.     while((mp = getq(q)) != NULL) {
  4606.         /* we can only get M_DATA types into our Queue, due to our Put function */
  4607.         m0 = mp;    /* remember first message block */
  4608.         ph = (struct ppp_header *) mp->b_rptr;
  4609.         /* assume ppp_header is completely in first block */
  4610.         if(mp->b_wptr - mp->b_rptr < sizeof(struct ppp_header)) {
  4611.             freemsg(mp);
  4612.             p->pii_ifnet.if_ierrors++;
  4613.             continue;
  4614. d531 32
  4615. a562 45
  4616. #ifdef    VJC
  4617.         switch (ntohs(ph->ph_protocol)) {
  4618.             case PPP_IP :
  4619.                 break;
  4620.             case PPP_VJC_COMP :
  4621.                 if(p->pii_flags & PII_FLAGS_VJC_ON) {
  4622.                     for(xlen=0, mvjc = mp; mvjc; mvjc = mvjc->b_cont)
  4623.                         xlen += (mvjc->b_wptr - mvjc->b_rptr);
  4624.                     xlen -= sizeof(struct ppp_header);
  4625.                     if(!(mvjc = allocb(128, BPRI_MED))) {    /* get a 128 byte buffer for IP header*/
  4626.                         putbq(q,mp);
  4627.                         qenable(q);
  4628.                         return;
  4629.                     }
  4630.                     mvjc->b_wptr += 128;
  4631.                     linkb(mvjc,mp);
  4632.                     if(!pullupmsg(mvjc,-1)) {    /* string em all together. ugh what a waste */
  4633.                         freemsg(mvjc);
  4634.                         continue;
  4635.                     }
  4636.                     cp = mvjc->b_rptr + 128 + sizeof(struct ppp_header);
  4637.                     m0 = mp = mvjc;
  4638.                     xlen = sl_uncompress_tcp(&cp,xlen, TYPE_COMPRESSED_TCP, &p->pii_sc_comp);
  4639.                     if(!xlen) {
  4640.                         DLOG("ppp: sl_uncompress failed on type Compressed",0);;
  4641.                         goto reject;
  4642.                     }
  4643.                     mp->b_rptr = cp - sizeof(struct ppp_header);
  4644.                     ((struct ppp_header *) mp->b_rptr)->ph_protocol = htons(PPP_IP);
  4645.                     break;
  4646.                 }
  4647.                     
  4648.             case PPP_VJC_UNCOMP :
  4649.                 if(p->pii_flags & PII_FLAGS_VJC_ON) {
  4650.                     cp = (unsigned char *) mp->b_rptr + sizeof(struct ppp_header);
  4651.                     if(sl_uncompress_tcp(&cp, 1, TYPE_UNCOMPRESSED_TCP, &p->pii_sc_comp)) {
  4652.                         ((struct ppp_header *) mp->b_rptr)->ph_protocol = htons(PPP_IP);
  4653.                         break;
  4654.                     }
  4655.                     DLOG("ppp: sl_uncompress failed on type Uncompresed\n",0);
  4656. reject:;
  4657.                         freemsg(mp);
  4658.                         continue;                
  4659.                 }
  4660.             default :;
  4661. d565 1
  4662. a565 1
  4663.             if(ntohs(ph->ph_protocol) != PPP_IP) {
  4664. d567 21
  4665. a587 9
  4666.                 DLOG("ppp: unknown protocol 0x%x\n",ntohs(ph->ph_protocol));
  4667.                 INCR(sl_ipackets);
  4668.                 if(!canput(q->q_next)) {
  4669.                     putbq(q, mp);
  4670.                     return;
  4671.                 }
  4672.                 putnext(q,mp);
  4673.                 p->pii_ifnet.if_ipackets++;
  4674.                 continue;
  4675. d589 1
  4676. a589 1
  4677.                 }
  4678. d591 26
  4679. a616 26
  4680.         }
  4681.         len  = 0;
  4682.         mb1 = NULL;
  4683.         xlen = mp->b_wptr - (rptr = mp->b_rptr);
  4684.         while(mp) {
  4685.             if(len < 1) {
  4686.                 MGET(mb2, M_DONTWAIT, MT_DATA);
  4687.                 if(!mb2) {
  4688.                     p->pii_ifnet.if_ierrors++;
  4689.                     putbq(q,m0);
  4690.                     qenable(q);
  4691.                     if(mb1)
  4692.                         m_freem(mb1);    /* discard what we've used already */
  4693.                     return;
  4694.                 }            /* if we couldn't get a buffer, put back the message and try later */
  4695.                 len = MLEN;
  4696.                 mb2->m_len = 0;
  4697.                 if(mb1) {
  4698.                     mbtail->m_next = mb2;
  4699.                     mbtail = mb2;
  4700.                 }
  4701.                 else 
  4702.                     mbtail = mb1 = mb2;
  4703.             }
  4704.             count = MIN(xlen, len);
  4705.             bcopy((char *) rptr, mtod(mb2, char *) + mb2->m_len, count);
  4706. d618 1
  4707. a618 1
  4708.             p->pii_stats.sl_ibytes += count;
  4709. d620 10
  4710. a629 10
  4711.             rptr += count;
  4712.             len -= count;
  4713.             xlen -= count;
  4714.             mb2->m_len += count;
  4715.             if(!xlen) {    /* move to the next mblk */
  4716.                 mp = mp->b_cont;
  4717.                 if(mp)
  4718.                     xlen = mp->b_wptr - (rptr = mp->b_rptr);
  4719.             }
  4720.         }
  4721. d631 1
  4722. a631 1
  4723.             /* note, HADJ >= 0 is assumed */
  4724. d633 19
  4725. a651 19
  4726.         ifp = (struct ifnet **) (mtod(mb1, u_char *) + HADJ);
  4727.         *ifp =  &p->pii_ifnet;    /* stick ifnet * in front of packet */
  4728.         mb1->m_off += HADJ;
  4729.         mb1->m_len -= HADJ;
  4730.         freemsg(m0);
  4731.         p->pii_ifnet.if_ipackets++;
  4732.         INCR(sl_ipackets);
  4733.         s = splimp();
  4734.         if (IF_QFULL(&ipintrq)) {
  4735.             IF_DROP(&ipintrq);
  4736.             p->pii_ifnet.if_ierrors++;
  4737.             m_freem(mb1);
  4738.         }
  4739.         else {
  4740.             IF_ENQUEUE(&ipintrq, mb1);
  4741.             schednetisr(NETISR_IP);
  4742.         }
  4743.         splx(s);
  4744.     }    /* end while */
  4745. d657 4
  4746. a660 4
  4747. ppp_output(ifp, m0, dst)
  4748.     struct ifnet *ifp;
  4749.     struct mbuf *m0;
  4750.     struct sockaddr *dst;
  4751. d662 6
  4752. a667 8
  4753.     register PII    *p = &pii[ifp->if_unit];
  4754.     struct mbuf    *m1;
  4755.     int    error,s, len;
  4756.     u_short    protocol;
  4757. #ifdef    VJC
  4758.     u_char    type;
  4759. #endif
  4760.     mblk_t    *mp;
  4761. d669 41
  4762. a709 2
  4763.     error = 0;
  4764.     if((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING || !p->pii_writeq) {
  4765. d712 9
  4766. d722 4
  4767. d727 7
  4768. a733 1
  4769.     switch    (dst->sa_family) {
  4770. d735 3
  4771. a737 3
  4772.         case AF_INET :
  4773.             protocol = PPP_IP;
  4774.             break;
  4775. d740 3
  4776. a742 3
  4777.         case AF_NS :
  4778.             protocol = PPP_XNS;
  4779.             break;
  4780. d744 13
  4781. a756 4
  4782.         default :;
  4783.             printf("ppp%d: af%d not supported\n",ifp->if_unit, dst->sa_family);
  4784.             error = EAFNOSUPPORT;
  4785.             goto getout;
  4786. d758 40
  4787. d799 24
  4788. a822 15
  4789.     if((protocol == PPP_IP) && (p->pii_flags & PII_FLAGS_VJC_ON)) {
  4790.         register struct ip *ip;
  4791.         ip = mtod(m0, struct ip *);
  4792.         if(ip->ip_p == IPPROTO_TCP) {
  4793.             type = sl_compress_tcp(m0, ip, &p->pii_sc_comp, 1);
  4794.             switch (type) {
  4795.         
  4796.                 case TYPE_UNCOMPRESSED_TCP :
  4797.                     protocol = PPP_VJC_UNCOMP;
  4798.                     break;
  4799.                 case TYPE_COMPRESSED_TCP :
  4800.                     protocol = PPP_VJC_COMP;
  4801.                     break;    
  4802.                 default :;
  4803.             }
  4804. d824 1
  4805. d828 16
  4806. a843 14
  4807.     for(m1 = m0; m1; m1 = m1->m_next) 
  4808.         len += m1->m_len;
  4809.     if(!(p->pii_flags & PII_FLAGS_COMPAC))
  4810.         len += 2;        /* if we are not compac, then need 2 extra bytes */
  4811.     if(p->pii_flags & PII_FLAGS_COMPPROT)
  4812.         len += 1;
  4813.     else
  4814.         len += 2;        /* we never need to check the actual protocol, since its always
  4815.                        either PPP_IP,PPP_VJC_* or PPP_XNS
  4816.                     */
  4817.  
  4818.     if(!(mp = allocb(len, BPRI_LO))) {
  4819.         error = ENOBUFS;
  4820.         goto getout;
  4821. d848 3
  4822. a850 3
  4823.     if(!(p->pii_flags & PII_FLAGS_COMPAC)) {
  4824.         *mp->b_wptr++ = PPP_ALLSTATIONS;
  4825.         *mp->b_wptr++ = PPP_UI;
  4826. d852 2
  4827. a853 2
  4828.     if(!(p->pii_flags & PII_FLAGS_COMPPROT))
  4829.         *mp->b_wptr++ = 0;
  4830. d855 3
  4831. a857 3
  4832.     for(m1 = m0; m1; m1 = m1->m_next) {        /* copy all data */
  4833.         bcopy(mtod(m1, char *), (char *) mp->b_wptr, m1->m_len);
  4834.         mp->b_wptr += m1->m_len;
  4835. d859 1
  4836. d862 1
  4837. a863 1
  4838.     splx(s);
  4839. a865 1
  4840. getout:;
  4841. d867 2
  4842. a868 5
  4843.     if(error) {
  4844.         INCR(sl_oerrors);
  4845.         p->pii_ifnet.if_oerrors++;
  4846.     }
  4847.     return(error);        /* gads, streams are great */
  4848. d874 4
  4849. a877 4
  4850. ppp_ioctl(ifp, cmd, data)
  4851.     register struct ifnet *ifp;
  4852.     int    cmd;
  4853.     caddr_t    data;
  4854. d879 3
  4855. a881 3
  4856.     register struct ifaddr *ifa = (struct ifaddr *) data;
  4857.     register struct ifreq *ifr = (struct ifreq *) data;
  4858.     int    s = splimp(), error = 0;
  4859. d883 10
  4860. a892 3
  4861.     if(ifa == NULL ) {
  4862.         splx(s);
  4863.         return(EFAULT);
  4864. d894 15
  4865. d910 4
  4866. a913 39
  4867.     switch    (cmd)    {
  4868.         case SIOCSIFFLAGS :
  4869.             if(!suser()) {
  4870.                 error = EPERM;
  4871.                 break;
  4872.             }
  4873.             ifp->if_flags &= (IFF_CANTCHANGE);    /* clear the flags that can be cleared */
  4874.             ifp->if_flags |= (ifr->ifr_flags & ~IFF_CANTCHANGE); /* or in the flags that can
  4875.                                         be changed */
  4876.             break;
  4877.         case SIOCGIFFLAGS :
  4878.             ifr->ifr_flags = ifp->if_flags;
  4879.             break;
  4880.         case SIOCSIFADDR :
  4881.             if( ifa->ifa_addr.sa_family != AF_INET) 
  4882.                 error = EAFNOSUPPORT;
  4883.             break;
  4884.         case SIOCSIFDSTADDR :
  4885.             if(ifa->ifa_addr.sa_family != AF_INET)
  4886.                 error = EAFNOSUPPORT;
  4887.             break;
  4888.  
  4889.         case SIOCSIFMTU :
  4890.             if(!suser()) {
  4891.                 error = EPERM;
  4892.                 break;
  4893.             }
  4894.             if(ifr->ifr_mtu > (4096 - (sizeof(struct ppp_header) + sizeof(u_short)))) {
  4895.                 error = EINVAL;
  4896.                 break;
  4897.             }
  4898.             ifp->if_mtu = ifr->ifr_mtu;
  4899.             break;
  4900.         case SIOCGIFMTU :
  4901.             ifr->ifr_mtu = ifp->if_mtu;
  4902.             break;
  4903.         default :;
  4904.             error = EINVAL;
  4905.             break;
  4906. d915 16
  4907. a930 2
  4908.     splx(s);
  4909.     return(error);
  4910. d933 90
  4911. @
  4912.